diff options
-rw-r--r-- | libusb/core.c | 30 | ||||
-rw-r--r-- | libusb/hotplug.c | 9 | ||||
-rw-r--r-- | libusb/io.c | 21 | ||||
-rw-r--r-- | libusb/libusbi.h | 4 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
5 files changed, 41 insertions, 25 deletions
diff --git a/libusb/core.c b/libusb/core.c index 626fabc..9894209 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1200,13 +1200,16 @@ int usbi_clear_event(struct libusb_context *ctx) */ void usbi_fd_notification(struct libusb_context *ctx) { - /* record that there is a new poll fd */ + int pending_events; + + /* Record that there is a new poll fd. + * Only signal an event if there are no prior pending events. */ usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); ctx->fd_notify = 1; + if (!pending_events) + usbi_signal_event(ctx); usbi_mutex_unlock(&ctx->event_data_lock); - - /* signal the event pipe to interrupt event handlers */ - usbi_signal_event(ctx); } /** \ingroup dev @@ -1407,6 +1410,7 @@ static void do_close(struct libusb_context *ctx, void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) { struct libusb_context *ctx; + int pending_events; if (!dev_handle) return; @@ -1420,26 +1424,28 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) * thread from doing event handling) because we will be removing a file * descriptor from the polling loop. */ - /* record that we are closing a device */ + /* Record that we are closing a device. + * Only signal an event if there are no prior pending events. */ usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); ctx->device_close++; + if (!pending_events) + usbi_signal_event(ctx); usbi_mutex_unlock(&ctx->event_data_lock); - /* signal the event pipe to interrupt event handlers */ - usbi_signal_event(ctx); - /* take event handling lock */ libusb_lock_events(ctx); - /* clear the event pipe */ - usbi_clear_event(ctx); - /* Close the device */ do_close(ctx, dev_handle); - /* we're done with closing this device */ + /* We're done with closing this device. + * Clear the event pipe if there are no further pending events. */ usbi_mutex_lock(&ctx->event_data_lock); ctx->device_close--; + pending_events = usbi_pending_events(ctx); + if (!pending_events) + usbi_clear_event(ctx); usbi_mutex_unlock(&ctx->event_data_lock); /* Release event handling lock and wake up event waiters */ diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 9171f2c..3ac159f 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -206,6 +206,7 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event) { + int pending_events;; libusb_hotplug_message *message = calloc(1, sizeof(*message)); if (!message) { @@ -216,12 +217,14 @@ void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device message->event = event; message->device = dev; - /* Take the event data lock and add this message to the list. */ + /* Take the event data lock and add this message to the list. + * Only signal an event if there are no prior pending events. */ usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); list_add_tail(&message->list, &ctx->hotplug_msgs); + if (!pending_events) + usbi_signal_event(ctx); usbi_mutex_unlock(&ctx->event_data_lock); - - usbi_signal_event(ctx); } int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, diff --git a/libusb/io.c b/libusb/io.c index 6ae4f8d..a5fda69 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2029,7 +2029,6 @@ redo_poll: /* fds[0] is always the event pipe */ if (fds[0].revents) { - unsigned int ru; libusb_hotplug_message *message = NULL; usbi_dbg("caught a fish on the event pipe"); @@ -2037,8 +2036,15 @@ redo_poll: /* take the the event data lock while processing events */ usbi_mutex_lock(&ctx->event_data_lock); + /* check if someone added a new poll fd */ + if (ctx->fd_notify) { + usbi_dbg("someone updated the poll fds"); + ctx->fd_notify = 0; + } + /* check if someone is closing a device */ - ru = ctx->device_close; + if (ctx->device_close) + usbi_dbg("someone is closing a device"); /* check for any pending hotplug messages */ if (!list_empty(&ctx->hotplug_msgs)) { @@ -2048,6 +2054,10 @@ redo_poll: list_del(&message->list); } + /* if no further pending events, clear the event pipe */ + if (!usbi_pending_events(ctx)) + usbi_clear_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); /* process the hotplug message, if any */ @@ -2061,13 +2071,6 @@ redo_poll: free(message); } - /* clear the event pipe if this was an fd or hotplug notification */ - if (!ru || message) { - r = usbi_clear_event(ctx); - if (r) - goto handled; - } - if (0 == --r) goto handled; } diff --git a/libusb/libusbi.h b/libusb/libusbi.h index c94c5a2..2d2f71a 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -317,6 +317,10 @@ struct libusb_context { struct list_head list; }; +/* Update the following macro if new event sources are added */ +#define usbi_pending_events(ctx) \ + ((ctx)->device_close || (ctx)->fd_notify || !list_empty(&(ctx)->hotplug_msgs)) + #ifdef USBI_TIMERFD_AVAILABLE #define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) #else diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 90d77c5..dad6c22 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10938 +#define LIBUSB_NANO 10939 |