Title: [188415] trunk/Source/WTF
Revision
188415
Author
mark....@apple.com
Date
2015-08-13 16:38:57 -0700 (Thu, 13 Aug 2015)

Log Message

WorkQueue::dispatchAfter() on Windows fires early.
https://bugs.webkit.org/show_bug.cgi?id=147992

Reviewed by Brent Fulgham.

The Windows implementation of WorkQueue::dispatchAfter() uses CreateTimerQueueTimer().
Unfortunately, CreateTimerQueueTimer() is sloppy and can fire early.  We need to compensate
for this slop to ensure that the specified duration does expire before the callback function
is called.  Otherwise, the JSC watchdog (which depends on this) can fail randomly.

* wtf/win/WorkQueueWin.cpp:
(WTF::WorkQueue::dispatchAfter):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (188414 => 188415)


--- trunk/Source/WTF/ChangeLog	2015-08-13 23:26:57 UTC (rev 188414)
+++ trunk/Source/WTF/ChangeLog	2015-08-13 23:38:57 UTC (rev 188415)
@@ -1,3 +1,18 @@
+2015-08-13  Mark Lam  <mark....@apple.com>
+
+        WorkQueue::dispatchAfter() on Windows fires early.
+        https://bugs.webkit.org/show_bug.cgi?id=147992
+
+        Reviewed by Brent Fulgham.
+
+        The Windows implementation of WorkQueue::dispatchAfter() uses CreateTimerQueueTimer().
+        Unfortunately, CreateTimerQueueTimer() is sloppy and can fire early.  We need to compensate
+        for this slop to ensure that the specified duration does expire before the callback function
+        is called.  Otherwise, the JSC watchdog (which depends on this) can fail randomly.
+
+        * wtf/win/WorkQueueWin.cpp:
+        (WTF::WorkQueue::dispatchAfter):
+
 2015-08-13  Filip Pizlo  <fpi...@apple.com>
 
         WTF should have a compact Condition object to use with Lock

Modified: trunk/Source/WTF/wtf/win/WorkQueueWin.cpp (188414 => 188415)


--- trunk/Source/WTF/wtf/win/WorkQueueWin.cpp	2015-08-13 23:26:57 UTC (rev 188414)
+++ trunk/Source/WTF/wtf/win/WorkQueueWin.cpp	2015-08-13 23:38:57 UTC (rev 188415)
@@ -195,9 +195,22 @@
         // timer handle has been stored in it.
         MutexLocker lock(context->timerMutex);
 
+        int64_t milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
+
+        // From empirical testing, we've seen CreateTimerQueueTimer() sometimes fire up to 5+ ms early.
+        // This causes havoc for clients of this code that expect to not be called back until the
+        // specified duration has expired. Other folks online have also observed some slop in the
+        // firing times of CreateTimerQuqueTimer(). From the data posted at
+        // http://omeg.pl/blog/2011/11/on-winapi-timers-and-their-resolution, it appears that the slop
+        // can be up to about 10 ms. To ensure that we don't fire the timer early, we'll tack on a
+        // slop adjustment to the duration, and we'll use double the worst amount of slop observed
+        // so far.
+        const int64_t slopAdjustment = 20;
+        if (milliseconds) 
+            milliseconds += slopAdjustment;
+
         // Since our timer callback is quick, we can execute in the timer thread itself and avoid
         // an extra thread switch over to a worker thread.
-        int64_t milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
         if (!::CreateTimerQueueTimer(&context->timer, m_timerQueue, timerCallback, context.get(), clampTo<DWORD>(milliseconds), 0, WT_EXECUTEINTIMERTHREAD)) {
             ASSERT_WITH_MESSAGE(false, "::CreateTimerQueueTimer failed with error %lu", ::GetLastError());
             return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to