This adds in new internal APIs to allow backends to reserve the pollfds which will be added to the pollfds linked list.
This also adds a new function for adding pre-reserved pollfds to the pollfds linked list. This function can never fail, unlike the standard usbi_add_pollfds(). --- libusb/io.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- libusb/libusbi.h | 5 +++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index d6eb3b5..f9056b2 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1061,6 +1061,7 @@ int usbi_io_init(struct libusb_context *ctx) list_init(&ctx->flying_transfers); list_init(&ctx->pollfds); ctx->pollfds_cnt = 0; + ctx->pollfds_reserved_cnt = 0; /* FIXME should use an eventfd on kernels that support it */ r = usbi_pipe(ctx->ctrl_pipe); @@ -2408,19 +2409,47 @@ void API_EXPORTED libusb_set_event_notifiers(libusb_context *ctx, ctx->event_cb_user_data = user_data; } -/* Add an event handle to the list of event handles to be monitored. - * events should be specified as a bitmask of libusb_event_direction. */ -int usbi_add_pollfd(struct libusb_context *ctx, libusb_event_handle handle, short events) +int usbi_reserve_pollfd(struct libusb_context *ctx, struct usbi_pollfd **ipollfd) { - struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd)); - if (!ipollfd) + int r = LIBUSB_SUCCESS; + usbi_mutex_lock(&ctx->pollfds_lock); +#ifdef MAXIMUM_POLL_FDS + if (ctx->pollfds_reserved_cnt + ctx->pollfds_cnt >= MAXIMUM_POLL_FDS) { + usbi_err(ctx, "Number of pollfd would exceed OS limitation of %d", + MAXIMUM_POLL_FDS); + r = LIBUSB_ERROR_NOT_SUPPORTED; + } else +#endif + ++ctx->pollfds_reserved_cnt; + usbi_mutex_unlock(&ctx->pollfds_lock); + if (r != LIBUSB_SUCCESS) { + *ipollfd = NULL; + return r; + } + *ipollfd = malloc(sizeof(**ipollfd)); + if (!*ipollfd) return LIBUSB_ERROR_NO_MEM; + return LIBUSB_SUCCESS; +} + +void usbi_unreserve_pollfd(struct libusb_context *ctx, struct usbi_pollfd *ipollfd) +{ + usbi_mutex_lock(&ctx->pollfds_lock); + --ctx->pollfds_reserved_cnt; + usbi_mutex_unlock(&ctx->pollfds_lock); + free(ipollfd); +} + +void usbi_add_reserved_pollfd(struct libusb_context *ctx, + libusb_event_handle handle, short events, struct usbi_pollfd *ipollfd) +{ usbi_dbg("add handle %d events %d", handle, events); ipollfd->pollfd.handle = handle; ipollfd->pollfd.direction = poll_events_to_event_dirs(events); usbi_mutex_lock(&ctx->pollfds_lock); list_add_tail(&ipollfd->list, &ctx->pollfds); + --ctx->pollfds_reserved_cnt; ++ctx->pollfds_cnt; usbi_mutex_unlock(&ctx->pollfds_lock); @@ -2430,6 +2459,17 @@ int usbi_add_pollfd(struct libusb_context *ctx, libusb_event_handle handle, shor #endif if (ctx->event_added_cb) ctx->event_added_cb(handle, events, ctx->event_cb_user_data); +} + +/* Add an event handle to the list of event handles to be monitored. + * events should be specified as a bitmask of libusb_event_direction. */ +int usbi_add_pollfd(struct libusb_context *ctx, libusb_event_handle handle, short events) +{ + struct usbi_pollfd *ipollfd; + int r = usbi_reserve_pollfd(ctx, &ipollfd); + if (r != LIBUSB_SUCCESS) + return r; + usbi_add_reserved_pollfd(ctx, handle, events, ipollfd); return 0; } diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 52d39ff..5380f4e 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -248,6 +248,7 @@ struct libusb_context { /* list of poll fds */ struct list_head pollfds; size_t pollfds_cnt; + size_t pollfds_reserved_cnt; usbi_mutex_t pollfds_lock; /* a counter that is set when we want to interrupt event handling, in order @@ -471,6 +472,10 @@ struct usbi_pollfd { }; int usbi_add_pollfd(struct libusb_context *ctx, libusb_event_handle handle, short events); +void usbi_add_reserved_pollfd(struct libusb_context *ctx, + libusb_event_handle handle, short events, struct usbi_pollfd *ipollfd); +int usbi_reserve_pollfd(struct libusb_context *ctx, struct usbi_pollfd **ipollfd); +void usbi_unreserve_pollfd(struct libusb_context *ctx, struct usbi_pollfd *ipollfd); void usbi_remove_pollfd(struct libusb_context *ctx, libusb_event_handle handle); void usbi_fd_notification(struct libusb_context *ctx); -- 1.7.9.5 ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ libusbx-devel mailing list libusbx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libusbx-devel