From ad1690d686575baadf8aa0fa820b0438e1a4b9a4 Mon Sep 17 00:00:00 2001 From: binji Date: Wed, 5 Aug 2015 13:58:06 -0700 Subject: [PATCH] [futex] Avoid accumulation errors in futex wait timeout 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 | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/futex-emulation.cc b/src/futex-emulation.cc index b8168a8..39f43dd 100644 --- a/src/futex-emulation.cc +++ b/src/futex-emulation.cc @@ -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; -- 2.7.4