summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Haggett <simon.haggett@realvnc.com>2013-07-12 10:06:00 +0100
committerPete Batard <pete@akeo.ie>2013-08-08 00:43:57 +0100
commit69d88b7fef75aef4ab99b1086c5be84626aedceb (patch)
tree5eb161029cd92f756c196a7912f2a7906ab111cf
parentb3562727e9cb75bf503c476452c9378c79385e71 (diff)
downloadlibusb-69d88b7fef75aef4ab99b1086c5be84626aedceb.tar.gz
Windows: Fix race between windows_clock_gettime_threaded() and windows_clock_gettime()
* When the timer thread is created in windows_init(), it performs an initialisation phase in which it uses QueryPerformanceFrequency() to determine if there is a high resolution timer available, and sets hires_frequency and hires_ticks_to_ps appropriately. However, since windows_init() does not wait for this initialisation phase to complete, windows_clock_gettime() can be called before hires_frequency and hires_ticks_to_ps have been updated. This can result in windows_clock_gettime() temporarily returning real-time clock values even though the platform supports a monotonic clock. * See http://sourceforge.net/mailarchive/forum.php?thread_name=1373620013-3574-1-git-send-email-simon.haggett%40realvnc.com&forum_name=libusbx-devel
-rw-r--r--libusb/os/windows_usb.c13
-rw-r--r--libusb/version_nano.h2
2 files changed, 13 insertions, 2 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 63357b1..097029c 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -886,6 +886,12 @@ static int windows_init(struct libusb_context *ctx)
}
SetThreadAffinityMask(timer_thread, 0);
+ // Wait for timer thread to init before continuing.
+ if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
+ usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
+ goto init_exit;
+ }
+
// Create a hash table to store session ids. Second parameter is better if prime
htab_create(ctx, HTAB_SIZE);
}
@@ -2172,6 +2178,11 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
}
+ // Signal windows_init() that we're ready to service requests
+ if (ReleaseSemaphore(timer_response, 1, NULL) == 0) {
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
+ }
+
// Main loop - wait for requests
while (1) {
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0;
@@ -2206,7 +2217,7 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
if ( (nb_responses)
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
- usbi_dbg("unable to release timer semaphore %d: %s", windows_error_str(0));
+ usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
}
continue;
case 1: // time to quit
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 18d80c0..b8325ac 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10802
+#define LIBUSB_NANO 10803