[futex] Avoid accumulation errors in futex wait timeout
authorbinji <binji@chromium.org>
Wed, 5 Aug 2015 20:58:06 +0000 (13:58 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 5 Aug 2015 20:58:15 +0000 (20:58 +0000)
The code previously used a relative timeout and accumulated wait times to see
if the timeout was exceeded. Now we convert the timeout into an absolute time,
and always compare the current time against that.

BUG=v8:4357
R=machenbach@chromium.org
LOG=n

Review URL: https://codereview.chromium.org/1272733002

Cr-Commit-Position: refs/heads/master@{#30036}

src/futex-emulation.cc

index b8168a8..39f43dd 100644 (file)
@@ -101,18 +101,25 @@ Object* FutexEmulation::Wait(Isolate* isolate,
     }
   }
 
-  base::TimeDelta rel_time_left = rel_timeout;
+  base::Time start_time = base::Time::NowFromSystemTime();
+  base::Time timeout_time = start_time + rel_timeout;
 
   wait_list_.Pointer()->AddNode(node);
 
   Object* result;
 
   while (true) {
-    base::TimeDelta time_to_wait = (use_timeout && rel_time_left < kMaxWaitTime)
-                                       ? rel_time_left
-                                       : kMaxWaitTime;
+    base::Time current_time = base::Time::NowFromSystemTime();
+    if (use_timeout && current_time > timeout_time) {
+      result = Smi::FromInt(Result::kTimedOut);
+      break;
+    }
+
+    base::TimeDelta time_until_timeout = timeout_time - current_time;
+    base::TimeDelta time_to_wait =
+        (use_timeout && time_until_timeout < kMaxWaitTime) ? time_until_timeout
+                                                           : kMaxWaitTime;
 
-    base::Time start_time = base::Time::NowFromSystemTime();
     bool wait_for_result = node->cond_.WaitFor(mutex_.Pointer(), time_to_wait);
     USE(wait_for_result);
 
@@ -121,17 +128,8 @@ Object* FutexEmulation::Wait(Isolate* isolate,
       break;
     }
 
-    // Spurious wakeup or timeout.
-    base::Time end_time = base::Time::NowFromSystemTime();
-    base::TimeDelta waited_for = end_time - start_time;
-    rel_time_left -= waited_for;
-
-    if (use_timeout && rel_time_left < base::TimeDelta::FromMicroseconds(0)) {
-      result = Smi::FromInt(Result::kTimedOut);
-      break;
-    }
-
-    // Potentially handle interrupts before continuing to wait.
+    // Spurious wakeup or timeout. Potentially handle interrupts before
+    // continuing to wait.
     Object* interrupt_object = isolate->stack_guard()->HandleInterrupts();
     if (interrupt_object->IsException()) {
       result = interrupt_object;