core: Add helper functions to signal and clear the event pipe

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
This commit is contained in:
Chris Dickens
2014-11-17 23:53:11 -08:00
committed by Chris Dickens
parent 5b2f2e1185
commit 192adf437b
4 changed files with 46 additions and 29 deletions
+40 -20
View File
@@ -1172,18 +1172,50 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev)
}
/*
* Interrupt the iteration of the event handling thread, so that it picks
* up the new fd.
* Signal the event pipe so that the event handling thread will be
* interrupted to process an internal event.
*/
void usbi_fd_notification(struct libusb_context *ctx)
int usbi_signal_event(struct libusb_context *ctx)
{
unsigned char dummy = 1;
ssize_t r;
/* write some data on event pipe to interrupt event handlers */
r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
if (r != sizeof(dummy))
if (r != sizeof(dummy)) {
usbi_warn(ctx, "internal signalling write failed");
return LIBUSB_ERROR_IO;
}
return 0;
}
/*
* Clear the event pipe so that the event handling will no longer be
* interrupted.
*/
int usbi_clear_event(struct libusb_context *ctx)
{
unsigned char dummy;
ssize_t r;
/* read some data on event pipe to clear it */
r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
if (r != sizeof(dummy)) {
usbi_warn(ctx, "internal signalling read failed");
return LIBUSB_ERROR_IO;
}
return 0;
}
/*
* Interrupt the iteration of the event handling thread, so that it picks
* up the new fd.
*/
void usbi_fd_notification(struct libusb_context *ctx)
{
usbi_signal_event(ctx);
}
/** \ingroup dev
@@ -1384,8 +1416,6 @@ static void do_close(struct libusb_context *ctx,
void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
{
struct libusb_context *ctx;
unsigned char dummy = 1;
ssize_t r;
if (!dev_handle)
return;
@@ -1404,24 +1434,14 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
ctx->device_close++;
usbi_mutex_unlock(&ctx->event_data_lock);
/* write some data on event pipe to interrupt event handlers */
r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
if (r <= 0) {
usbi_warn(ctx, "internal signalling write failed, closing anyway");
do_close(ctx, dev_handle);
usbi_mutex_lock(&ctx->event_data_lock);
ctx->device_close--;
usbi_mutex_unlock(&ctx->event_data_lock);
return;
}
/* signal the event pipe to interrupt event handlers */
usbi_signal_event(ctx);
/* take event handling lock */
libusb_lock_events(ctx);
/* read the dummy data */
r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
if (r <= 0)
usbi_warn(ctx, "internal signalling read failed, closing anyway");
/* clear the event pipe */
usbi_clear_event(ctx);
/* Close the device */
do_close(ctx, dev_handle);
+2 -8
View File
@@ -2051,8 +2051,6 @@ redo_poll:
/* another thread wanted to interrupt event handling, and it succeeded!
* handle any other events that cropped up at the same time, and
* simply return */
ssize_t ret;
unsigned char dummy;
unsigned int ru;
usbi_dbg("caught a fish on the event pipe");
@@ -2063,13 +2061,9 @@ redo_poll:
ru = ctx->device_close;
usbi_mutex_unlock(&ctx->event_data_lock);
if (!ru) {
ret = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
if (ret != sizeof(dummy)) {
usbi_err(ctx, "event pipe read error %d err=%d",
ret, errno);
r = LIBUSB_ERROR_OTHER;
r = usbi_clear_event(ctx);
if (r)
goto handled;
}
}
if (0 == --r)
+3
View File
@@ -462,6 +462,9 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
void usbi_connect_device (struct libusb_device *dev);
void usbi_disconnect_device (struct libusb_device *dev);
int usbi_signal_event(struct libusb_context *ctx);
int usbi_clear_event(struct libusb_context *ctx);
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU)
#include <unistd.h>
+1 -1
View File
@@ -1 +1 @@
#define LIBUSB_NANO 10935
#define LIBUSB_NANO 10936