libusb_device mutex protection
authorDaniel Drake <dsd@gentoo.org>
Fri, 18 Apr 2008 22:58:54 +0000 (23:58 +0100)
committerDaniel Drake <dsd@gentoo.org>
Fri, 18 Apr 2008 22:58:54 +0000 (23:58 +0100)
libusb/core.c
libusb/libusbi.h

index 3bce9a1..450c5fb 100644 (file)
@@ -235,9 +235,15 @@ struct libusb_device *usbi_alloc_device(unsigned long session_id)
 {
        size_t priv_size = usbi_backend->device_priv_size;
        struct libusb_device *dev = malloc(sizeof(*dev) + priv_size);
+       int r;
+
        if (!dev)
                return NULL;
 
+       r = pthread_mutex_init(&dev->lock, NULL);
+       if (r)
+               return NULL;
+
        dev->refcnt = 1;
        dev->session_data = session_id;
        memset(&dev->os_priv, 0, priv_size);
@@ -344,7 +350,9 @@ API_EXPORTED void libusb_free_device_list(struct libusb_device **list,
  */
 API_EXPORTED struct libusb_device *libusb_device_ref(struct libusb_device *dev)
 {
+       pthread_mutex_lock(&dev->lock);
        dev->refcnt++;
+       pthread_mutex_unlock(&dev->lock);
        return dev;
 }
 
@@ -355,10 +363,16 @@ API_EXPORTED struct libusb_device *libusb_device_ref(struct libusb_device *dev)
  */
 API_EXPORTED void libusb_device_unref(struct libusb_device *dev)
 {
+       int refcnt;
+
        if (!dev)
                return;
 
-       if (--dev->refcnt == 0) {
+       pthread_mutex_lock(&dev->lock);
+       refcnt = --dev->refcnt;
+       pthread_mutex_unlock(&dev->lock);
+
+       if (refcnt == 0) {
                usbi_dbg("destroy device %04x:%04x", dev->desc.idVendor,
                        dev->desc.idProduct);
 
index 19b28b6..7436491 100644 (file)
@@ -143,8 +143,12 @@ void usbi_log(enum usbi_log_level, const char *function, const char *format, ...
 #define usbi_err(fmt...) _usbi_log(LOG_LEVEL_ERROR, fmt)
 
 struct libusb_device {
-       struct list_head list;
+       /* lock protects refcnt, everything else is finalized at initialization
+        * time */
+       pthread_mutex_t lock;
        int refcnt;
+
+       struct list_head list;
        unsigned long session_data;
        struct libusb_device_descriptor desc;
        struct libusb_config_descriptor *config;