summaryrefslogtreecommitdiff
path: root/libusb/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/io.c')
-rw-r--r--libusb/io.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/libusb/io.c b/libusb/io.c
index c94df17..08e3d61 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1703,6 +1703,51 @@ static int handle_timeouts(struct libusb_context *ctx)
return 0;
}
#else
+/* Note: there is code duplication between handle_timeouts_locked and
+ * handle_timeouts, as tranfer cancellation from the backend requires
+ * flying_transfers locks that are not set wholesale */
+static int handle_timeouts_locked(struct libusb_context *ctx)
+{
+ int r;
+ struct timespec systime_ts;
+ struct timeval systime;
+ struct usbi_transfer *transfer;
+
+ if (list_empty(&ctx->flying_transfers))
+ return 0;
+
+ /* get current time */
+ r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
+ if (r < 0)
+ return r;
+
+ TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
+
+ /* iterate through flying transfers list, finding all transfers that
+ * have expired timeouts */
+ list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+ struct timeval *cur_tv = &transfer->timeout;
+
+ /* if we've reached transfers of infinite timeout, we're all done */
+ if (!timerisset(cur_tv))
+ return 0;
+
+ /* ignore timeouts we've already handled */
+ if (transfer->flags & USBI_TRANSFER_TIMED_OUT)
+ continue;
+
+ /* if transfer has non-expired timeout, nothing more to do */
+ if ((cur_tv->tv_sec > systime.tv_sec) ||
+ (cur_tv->tv_sec == systime.tv_sec &&
+ cur_tv->tv_usec > systime.tv_usec))
+ return 0;
+
+ /* otherwise, we've got an expired timeout to handle */
+ handle_timeout(transfer);
+ }
+ return 0;
+}
+
static int handle_timeouts(struct libusb_context *ctx)
{
int r;