mutex protection for device and handle lists
authorDaniel Drake <dsd@gentoo.org>
Fri, 18 Apr 2008 22:42:40 +0000 (23:42 +0100)
committerDaniel Drake <dsd@gentoo.org>
Fri, 18 Apr 2008 22:42:40 +0000 (23:42 +0100)
libusb/core.c
libusb/io.c
libusb/libusbi.h
libusb/os/linux_usbfs.c

index f90ea06..3bce9a1 100644 (file)
@@ -37,7 +37,10 @@ const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend;
 #endif
 
 static struct list_head usb_devs;
+static pthread_mutex_t usb_devs_lock = PTHREAD_MUTEX_INITIALIZER;
+
 struct list_head usbi_open_devs;
+pthread_mutex_t usbi_open_devs_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /**
  * \mainpage libusb-1.0 API Reference
@@ -237,20 +240,28 @@ struct libusb_device *usbi_alloc_device(unsigned long session_id)
 
        dev->refcnt = 1;
        dev->session_data = session_id;
-       list_add(&dev->list, &usb_devs);
        memset(&dev->os_priv, 0, priv_size);
+
+       pthread_mutex_lock(&usb_devs_lock);
+       list_add(&dev->list, &usb_devs);
+       pthread_mutex_unlock(&usb_devs_lock);
        return dev;
 }
 
 struct libusb_device *usbi_get_device_by_session_id(unsigned long session_id)
 {
        struct libusb_device *dev;
+       struct libusb_device *ret = NULL;
 
+       pthread_mutex_lock(&usb_devs_lock);
        list_for_each_entry(dev, &usb_devs, list)
-               if (dev->session_data == session_id)
-                       return dev;
+               if (dev->session_data == session_id) {
+                       ret = dev;
+                       break;
+               }
+       pthread_mutex_unlock(&usb_devs_lock);
 
-       return NULL;
+       return ret;
 }
 
 /** @ingroup dev
@@ -354,7 +365,10 @@ API_EXPORTED void libusb_device_unref(struct libusb_device *dev)
                if (usbi_backend->destroy_device)
                        usbi_backend->destroy_device(dev);
 
+               pthread_mutex_lock(&usb_devs_lock);
                list_del(&dev->list);
+               pthread_mutex_unlock(&usb_devs_lock);
+
                if (dev->config)
                        free(dev->config);
                free(dev);
@@ -392,7 +406,9 @@ API_EXPORTED struct libusb_device_handle *libusb_open(struct libusb_device *dev)
                return NULL;
        }
 
+       pthread_mutex_lock(&usbi_open_devs_lock);
        list_add(&handle->list, &usbi_open_devs);
+       pthread_mutex_unlock(&usbi_open_devs_lock);
        return handle;
 }
 
@@ -460,7 +476,10 @@ API_EXPORTED void libusb_close(struct libusb_device_handle *dev_handle)
                return;
        usbi_dbg("");
 
+       pthread_mutex_lock(&usbi_open_devs_lock);
        list_del(&dev_handle->list);
+       pthread_mutex_unlock(&usbi_open_devs_lock);
+
        do_close(dev_handle);
        free(dev_handle);
 }
@@ -545,12 +564,16 @@ API_EXPORTED void libusb_exit(void)
 {
        struct libusb_device_handle *devh;
        usbi_dbg("");
+
+       pthread_mutex_lock(&usbi_open_devs_lock);
        if (!list_empty(&usbi_open_devs)) {
                usbi_dbg("naughty app left some devices open!\n");
                list_for_each_entry(devh, &usbi_open_devs, list)
                        do_close(devh);
                /* FIXME where do the open handles get freed? */
        }
+       pthread_mutex_unlock(&usbi_open_devs_lock);
+
        if (usbi_backend->exit)
                usbi_backend->exit();
 }
index 5e0e92f..18ab594 100644 (file)
@@ -624,12 +624,14 @@ out:
 
 static int submit_transfer(struct usbi_transfer *itransfer)
 {
-       int r = usbi_backend->submit_transfer(itransfer);
+       int r;
+       
+       add_to_flying_list(itransfer);
+       r = usbi_backend->submit_transfer(itransfer);
        if (r < 0)
-               return r;
+               list_del(&itransfer->list);
 
-       add_to_flying_list(itransfer);
-       return 0;
+       return r;
 }
 
 /** \ingroup asyncio
index c589ef6..19b28b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <config.h>
 
 #include <endian.h>
+#include <pthread.h>
 #include <stddef.h>
 #include <sys/select.h>
 #include <time.h>
@@ -206,6 +207,7 @@ struct usb_descriptor_header {
 /* shared data and functions */
 
 extern struct list_head usbi_open_devs;
+extern pthread_mutex_t usbi_open_devs_lock;
 
 void usbi_io_init(void);
 
index 550fa08..2504fea 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <poll.h>
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1036,8 +1037,9 @@ static int reap_for_handle(struct libusb_device_handle *handle)
 static int op_handle_events(fd_set *readfds, fd_set *writefds)
 {
        struct libusb_device_handle *handle;
-       int r;
+       int r = 0;
 
+       pthread_mutex_lock(&usbi_open_devs_lock);
        list_for_each_entry(handle, &usbi_open_devs, list) {
                struct linux_device_handle_priv *hpriv = __device_handle_priv(handle);
                if (!FD_ISSET(hpriv->fd, writefds))
@@ -1046,10 +1048,13 @@ static int op_handle_events(fd_set *readfds, fd_set *writefds)
                if (r == -1 && errno == EAGAIN)
                        continue;
                if (r < 0)
-                       return r;
+                       goto out;
        }
 
-       return 0;
+       r = 0;
+out:
+       pthread_mutex_unlock(&usbi_open_devs_lock);
+       return r;
 }
 
 const struct usbi_os_backend linux_usbfs_backend = {