<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[188415] trunk/Source/WTF</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/188415">188415</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-08-13 16:38:57 -0700 (Thu, 13 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfwinWorkQueueWincpp">trunk/Source/WTF/wtf/win/WorkQueueWin.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (188414 => 188415)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2015-08-13  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        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):
+
</ins><span class="cx"> 2015-08-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WTF should have a compact Condition object to use with Lock
</span></span></pre></div>
<a id="trunkSourceWTFwtfwinWorkQueueWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/win/WorkQueueWin.cpp (188414 => 188415)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -195,9 +195,22 @@
</span><span class="cx">         // timer handle has been stored in it.
</span><span class="cx">         MutexLocker lock(context-&gt;timerMutex);
</span><span class="cx"> 
</span><ins>+        int64_t milliseconds = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(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;
+
</ins><span class="cx">         // Since our timer callback is quick, we can execute in the timer thread itself and avoid
</span><span class="cx">         // an extra thread switch over to a worker thread.
</span><del>-        int64_t milliseconds = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(duration).count();
</del><span class="cx">         if (!::CreateTimerQueueTimer(&amp;context-&gt;timer, m_timerQueue, timerCallback, context.get(), clampTo&lt;DWORD&gt;(milliseconds), 0, WT_EXECUTEINTIMERTHREAD)) {
</span><span class="cx">             ASSERT_WITH_MESSAGE(false, &quot;::CreateTimerQueueTimer failed with error %lu&quot;, ::GetLastError());
</span><span class="cx">             return;
</span></span></pre>
</div>
</div>

</body>
</html>