| Index: Source/platform/heap/ThreadState.cpp
|
| diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp
|
| index 25b50dd9a0fe927b6899bf912eb54c4ccfae8507..f26a4099423944926234bd9ffc256ecba8277de8 100644
|
| --- a/Source/platform/heap/ThreadState.cpp
|
| +++ b/Source/platform/heap/ThreadState.cpp
|
| @@ -97,6 +97,13 @@ static Mutex& threadAttachMutex()
|
| return mutex;
|
| }
|
|
|
| +static double lockingTimeout()
|
| +{
|
| + // Wait time for parking all threads is at most 500 MS.
|
| + return 0.100;
|
| +}
|
| +
|
| +
|
| typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
|
| extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback);
|
|
|
| @@ -106,7 +113,7 @@ public:
|
| ~SafePointBarrier() { }
|
|
|
| // Request other attached threads that are not at safe points to park themselves on safepoints.
|
| - void parkOthers()
|
| + bool parkOthers()
|
| {
|
| ASSERT(ThreadState::current()->isAtSafePoint());
|
|
|
| @@ -129,16 +136,30 @@ public:
|
| interruptors[i]->requestInterrupt();
|
| }
|
|
|
| - while (acquireLoad(&m_unparkedThreadCount) > 0)
|
| - m_parked.wait(m_mutex);
|
| + while (acquireLoad(&m_unparkedThreadCount) > 0) {
|
| + double expirationTime = currentTime() + lockingTimeout();
|
| + if (!m_parked.timedWait(m_mutex, expirationTime)) {
|
| + // One of the other threads did not return to a safepoint within the maximum
|
| + // time we allow for threads to be parked. Abandon the GC and resume the
|
| + // currently parked threads.
|
| + resumeOthers(true);
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| }
|
|
|
| - void resumeOthers()
|
| + void resumeOthers(bool barrierLocked = false)
|
| {
|
| ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
|
| atomicSubtract(&m_unparkedThreadCount, threads.size());
|
| releaseStore(&m_canResume, 1);
|
| - {
|
| +
|
| + // FIXME: Resumed threads will all contend for m_mutex just to unlock it
|
| + // later which is a waste of resources.
|
| + if (UNLIKELY(barrierLocked)) {
|
| + m_resume.broadcast();
|
| + } else {
|
| // FIXME: Resumed threads will all contend for
|
| // m_mutex just to unlock it later which is a waste of
|
| // resources.
|
| @@ -160,6 +181,28 @@ public:
|
| ASSERT(ThreadState::current()->isAtSafePoint());
|
| }
|
|
|
| + void checkAndPark(ThreadState* state)
|
| + {
|
| + ASSERT(!state->isSweepInProgress());
|
| + if (!acquireLoad(&m_canResume)) {
|
| + pushAllRegisters(this, state, parkAfterPushRegisters);
|
| + state->performPendingSweep();
|
| + }
|
| + }
|
| +
|
| + void enterSafePoint(ThreadState* state)
|
| + {
|
| + ASSERT(!state->isSweepInProgress());
|
| + pushAllRegisters(this, state, enterSafePointAfterPushRegisters);
|
| + }
|
| +
|
| + void leaveSafePoint(ThreadState* state)
|
| + {
|
| + if (atomicIncrement(&m_unparkedThreadCount) > 0)
|
| + checkAndPark(state);
|
| + }
|
| +
|
| +private:
|
| void doPark(ThreadState* state, intptr_t* stackEnd)
|
| {
|
| state->recordStackEnd(stackEnd);
|
| @@ -171,13 +214,9 @@ public:
|
| atomicIncrement(&m_unparkedThreadCount);
|
| }
|
|
|
| - void checkAndPark(ThreadState* state)
|
| + static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd)
|
| {
|
| - ASSERT(!state->isSweepInProgress());
|
| - if (!acquireLoad(&m_canResume)) {
|
| - pushAllRegisters(this, state, parkAfterPushRegisters);
|
| - state->performPendingSweep();
|
| - }
|
| + barrier->doPark(state, stackEnd);
|
| }
|
|
|
| void doEnterSafePoint(ThreadState* state, intptr_t* stackEnd)
|
| @@ -198,24 +237,6 @@ public:
|
| }
|
| }
|
|
|
| - void enterSafePoint(ThreadState* state)
|
| - {
|
| - ASSERT(!state->isSweepInProgress());
|
| - pushAllRegisters(this, state, enterSafePointAfterPushRegisters);
|
| - }
|
| -
|
| - void leaveSafePoint(ThreadState* state)
|
| - {
|
| - if (atomicIncrement(&m_unparkedThreadCount) > 0)
|
| - checkAndPark(state);
|
| - }
|
| -
|
| -private:
|
| - static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd)
|
| - {
|
| - barrier->doPark(state, stackEnd);
|
| - }
|
| -
|
| static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, ThreadState* state, intptr_t* stackEnd)
|
| {
|
| barrier->doEnterSafePoint(state, stackEnd);
|
| @@ -702,9 +723,9 @@ void ThreadState::getStats(HeapStats& stats)
|
| #endif
|
| }
|
|
|
| -void ThreadState::stopThreads()
|
| +bool ThreadState::stopThreads()
|
| {
|
| - s_safePointBarrier->parkOthers();
|
| + return s_safePointBarrier->parkOthers();
|
| }
|
|
|
| void ThreadState::resumeThreads()
|
|
|