diff options
author | Simon Haggett <simon.haggett@realvnc.com> | 2013-07-12 10:06:00 +0100 |
---|---|---|
committer | Pete Batard <pete@akeo.ie> | 2013-08-08 00:43:57 +0100 |
commit | 69d88b7fef75aef4ab99b1086c5be84626aedceb (patch) | |
tree | 5eb161029cd92f756c196a7912f2a7906ab111cf | |
parent | b3562727e9cb75bf503c476452c9378c79385e71 (diff) | |
download | libusb-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.c | 13 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |