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
[email protected]
https://lists.sourceforge.net/lists/listinfo/libusbx-devel