Handle a bunch of race conditions in the opening/closing of the devices. In particular:

- Provide a open_count atomic that stays set from the time the device is open until the very last moment it is closed
- Protecting the tracepoint registration with an atomic variable is not the right way to do it (multiple processes might execute the same part of the code at the same time if the right sequence of open()/close() is done on the devices) and wrap them in a critical section with a mutex