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.
This patch addresses this issue by having windows_init() wait until the timer thread has initialised before returning. Signed-off-by: Simon Haggett <simon.hagg...@realvnc.com> --- libusb/os/windows_usb.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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 -- 1.7.9.5 ------------------------------------------------------------------------------ See everything from the browser to the database with AppDynamics Get end-to-end visibility with application monitoring from AppDynamics Isolate bottlenecks and diagnose root cause in seconds. Start your free trial of AppDynamics Pro today! http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk _______________________________________________ libusbx-devel mailing list libusbx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libusbx-devel