Index: Source/platform/heap/ThreadState.cpp |
diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp |
index a8a66cb67fced14b8a90e6cafc677c3325ace37f..b6601b666d59a32f3c5fe813c44827169fcd1b1f 100644 |
--- a/Source/platform/heap/ThreadState.cpp |
+++ b/Source/platform/heap/ThreadState.cpp |
@@ -96,6 +96,13 @@ static Mutex& threadAttachMutex() |
return mutex; |
} |
+static double lockingTimeout() |
+{ |
+ // Wait time for parking all threads is at most 10 MS. |
+ return 0.01; |
+} |
+ |
+ |
typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*); |
extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback); |
@@ -105,7 +112,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()); |
@@ -128,16 +135,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); |
haraken
2014/05/01 04:03:56
Nit: It would be more consistent if you can remove
wibling-chromium
2014/05/01 06:51:48
Yes, that would be nice. However I am worried that
haraken
2014/05/01 07:33:50
Yes, but is it problematic that we allow another t
wibling-chromium
2014/05/01 08:25:18
No, that should be okay. However previously we wou
haraken
2014/05/01 08:36:31
Thanks for the clarification, makes sense!
|
+ return false; |
+ } |
+ } |
+ return true; |
} |
- void resumeOthers() |
+ void resumeOthers(bool barrierLocked = false) |
{ |
ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(); |
atomicSubtract(&m_unparkedThreadCount, threads.size()); |
haraken
2014/05/01 04:03:56
I guess this will confuse m_unparkedThreadCount. A
wibling-chromium
2014/05/01 06:51:48
I initially read the code the same way, but parkOt
haraken
2014/05/01 07:33:50
Thanks for the clarification. Your explanation sou
|
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. |
@@ -159,6 +180,28 @@ public: |
ASSERT(ThreadState::current()->isAtSafePoint()); |
} |
+ void checkAndPark(ThreadState* state) |
zerny-chromium
2014/05/01 07:05:38
Nit: avoid reordering/formatting for unchanged cod
wibling-chromium
2014/05/01 08:25:18
Done. I will revert that and do it in a separate c
|
+ { |
+ 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); |
@@ -170,13 +213,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) |
@@ -197,24 +236,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); |
@@ -701,9 +722,9 @@ void ThreadState::getStats(HeapStats& stats) |
#endif |
} |
-void ThreadState::stopThreads() |
+bool ThreadState::stopThreads() |
{ |
- s_safePointBarrier->parkOthers(); |
+ return s_safePointBarrier->parkOthers(); |
} |
void ThreadState::resumeThreads() |