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

Reply via email to