summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libusb/core.c16
-rw-r--r--libusb/libusbi.h6
2 files changed, 20 insertions, 2 deletions
diff --git a/libusb/core.c b/libusb/core.c
index 3bce9a1..450c5fb 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -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);
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 19b28b6..7436491 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -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;