WinCE: Fix race between wince_clock_gettime_threaded() and wince_clock_gettime()
authorSimon Haggett <simon.haggett@realvnc.com>
Fri, 12 Jul 2013 09:06:00 +0000 (10:06 +0100)
committerPete Batard <pete@akeo.ie>
Wed, 7 Aug 2013 23:41:46 +0000 (00:41 +0100)
* When the timer thread is created in wince_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 wince_init() does not wait for this initialisation
  phase to complete, wince_clock_gettime() can be called before hires_frequency
  and hires_ticks_to_ps have been updated. This can result in
  wince_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=1373619997-3535-1-git-send-email-simon.haggett%40realvnc.com&forum_name=libusbx-devel

libusb/os/wince_usb.c
libusb/version_nano.h

index e4a6633..90c129b 100644 (file)
@@ -234,6 +234,12 @@ static int wince_init(struct libusb_context *ctx)
                        usbi_err(ctx, "Unable to create timer thread - aborting");
                        goto init_exit;
                }
+
+               // 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;
+               }
        }
        // At this stage, either we went through full init successfully, or didn't need to
        r = LIBUSB_SUCCESS;
@@ -877,6 +883,11 @@ unsigned __stdcall wince_clock_gettime_threaded(void* param)
                usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
        }
 
+       // Signal wince_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;
@@ -911,7 +922,7 @@ unsigned __stdcall wince_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
index 81595be..18d80c0 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10801
+#define LIBUSB_NANO 10802