author | Lars T Hansen <lhansen@mozilla.com> |
Wed, 13 May 2015 10:35:42 +0200 | |
changeset 243660 | 2e7ce565cfc4df4aba77fe0de31893c524a96ca7 |
parent 243659 | 9bbb797f3e28edd6c850f10d55e3e7e189430d2b |
child 243661 | c48d5ce78376f7e19afc4702c7940db2f0838726 |
push id | 28744 |
push user | kwierso@gmail.com |
push date | Wed, 13 May 2015 18:12:16 +0000 |
treeherder | mozilla-central@324c3423deaf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | luke |
bugs | 1139856 |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/builtin/AtomicsObject.cpp | file | annotate | diff | comparison | revisions | |
js/src/builtin/AtomicsObject.h | file | annotate | diff | comparison | revisions |
--- a/js/src/builtin/AtomicsObject.cpp +++ b/js/src/builtin/AtomicsObject.cpp @@ -1027,17 +1027,23 @@ js::FutexRuntime::destroyInstance() { if (cond_) PR_DestroyCondVar(cond_); } bool js::FutexRuntime::isWaiting() { - return state_ == Waiting || state_ == WaitingInterrupted; + // When a worker is awoken for an interrupt it goes into state + // WaitingNotifiedForInterrupt for a short time before it actually + // wakes up and goes into WaitingInterrupted. In those states the + // worker is still waiting, and if an explicit wake arrives the + // worker transitions to Woken. See further comments in + // FutexRuntime::wait(). + return state_ == Waiting || state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt; } bool js::FutexRuntime::wait(JSContext* cx, double timeout_ms, AtomicsObject::FutexWaitResult* result) { MOZ_ASSERT(&cx->runtime()->fx == this); MOZ_ASSERT(lockHolder_ == PR_GetCurrentThread()); MOZ_ASSERT(state_ == Idle || state_ == WaitingInterrupted); @@ -1097,27 +1103,27 @@ js::FutexRuntime::wait(JSContext* cx, do } } break; case FutexRuntime::Woken: *result = AtomicsObject::FutexOK; goto finished; - case FutexRuntime::WokenForJSInterrupt: + case FutexRuntime::WaitingNotifiedForInterrupt: // The interrupt handler may reenter the engine. In that case // there are two complications: // // - The waiting thread is not actually waiting on the // condition variable so we have to record that it // should be woken when the interrupt handler returns. // To that end, we flag the thread as interrupted around // the interrupt and check state_ when the interrupt // handler returns. A futexWake() call that reaches the - // runtime during the interrupt sets state_ to woken. + // runtime during the interrupt sets state_ to Woken. // // - It is in principle possible for futexWait() to be // reentered on the same thread/runtime and waiting on the // same location and to yet again be interrupted and enter // the interrupt handler. In this case, it is important // that when another agent wakes waiters, all waiters using // the same runtime on the same location are woken in LIFO // order; FIFO may be the required order, but FIFO would @@ -1155,26 +1161,28 @@ finished: } void js::FutexRuntime::wake(WakeReason reason) { MOZ_ASSERT(lockHolder_ == PR_GetCurrentThread()); MOZ_ASSERT(isWaiting()); - if (state_ == WaitingInterrupted && reason == WakeExplicit) { + if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == WakeExplicit) { state_ = Woken; return; } switch (reason) { case WakeExplicit: state_ = Woken; break; case WakeForJSInterrupt: - state_ = WokenForJSInterrupt; + if (state_ == WaitingNotifiedForInterrupt) + return; + state_ = WaitingNotifiedForInterrupt; break; default: MOZ_CRASH(); } PR_NotifyCondVar(cond_); } const JSFunctionSpec AtomicsMethods[] = {
--- a/js/src/builtin/AtomicsObject.h +++ b/js/src/builtin/AtomicsObject.h @@ -92,29 +92,32 @@ public: // If the thread is not waiting then this method does nothing. // // If the thread is waiting in a call to futexWait() and the // reason is WakeExplicit then the futexWait() call will return // with Woken. // // If the thread is waiting in a call to futexWait() and the // reason is WakeForJSInterrupt then the futexWait() will return - // with WokenForJSInterrupt; in the latter case the caller of - // futexWait() must handle the interrupt. + // with WaitingNotifiedForInterrupt; in the latter case the caller + // of futexWait() must handle the interrupt. void wake(WakeReason reason); bool isWaiting(); private: enum FutexState { - Idle, // We are not waiting or woken - Waiting, // We are waiting, nothing has happened yet - WaitingInterrupted, // We are waiting, but have been interrupted - Woken, // Woken by a script call to futexWake - WokenForJSInterrupt // Woken by an interrupt handler + Idle, // We are not waiting or woken + Waiting, // We are waiting, nothing has happened yet + WaitingNotifiedForInterrupt, // We are waiting, but have been interrupted, + // and have not yet started running the + // interrupt handler + WaitingInterrupted, // We are waiting, but have been interrupted + // and are running the interrupt handler + Woken // Woken by a script call to futexWake }; // Condition variable that this runtime will wait on. PRCondVar* cond_; // Current futex state for this runtime. When not in a wait this // is Idle; when in a wait it is Waiting or the reason the futex // is about to wake up.