summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2014-11-17 23:53:14 -0800
committerChris Dickens <chris.dickens@hp.com>2014-12-19 11:22:03 -0800
commit89b5407b9aa74790a64b6f32a5b14a96242ba128 (patch)
treeb8436bce0ad29d67e072e984cf0b80544c2173d1
parent3b371f1a6ab30bdebdadfcde1b96a9b98fb806ca (diff)
downloadlibusb-89b5407b9aa74790a64b6f32a5b14a96242ba128.tar.gz
core: Signal the event pipe at most one time
This change will ensure that the event pipe is only signalled at most one time during the course of any incoming events. New events that occur while the event pipe is in the signalled state will not cause the event pipe to be signalled again. This change will provide support for the use of native events on the Windows/WinCE backends, as these events are binary and do not "count" the number of times they are signalled. Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r--libusb/core.c30
-rw-r--r--libusb/hotplug.c9
-rw-r--r--libusb/io.c21
-rw-r--r--libusb/libusbi.h4
-rw-r--r--libusb/version_nano.h2
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