| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef SafePoint_h | 5 #ifndef SafePoint_h |
| 6 #define SafePoint_h | 6 #define SafePoint_h |
| 7 | 7 |
| 8 #include "platform/heap/ThreadState.h" | 8 #include "platform/heap/ThreadState.h" |
| 9 #include "wtf/ThreadingPrimitives.h" | 9 #include "wtf/ThreadingPrimitives.h" |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 ~SafePointScope() { | 27 ~SafePointScope() { |
| 28 if (m_state) | 28 if (m_state) |
| 29 m_state->leaveSafePoint(); | 29 m_state->leaveSafePoint(); |
| 30 } | 30 } |
| 31 | 31 |
| 32 private: | 32 private: |
| 33 ThreadState* m_state; | 33 ThreadState* m_state; |
| 34 }; | 34 }; |
| 35 | 35 |
| 36 // The SafePointAwareMutexLocker is used to enter a safepoint while waiting for | |
| 37 // a mutex lock. It also ensures that the lock is not held while waiting for a | |
| 38 // GC to complete in the leaveSafePoint method, by releasing the lock if the | |
| 39 // leaveSafePoint method cannot complete without blocking, see | |
| 40 // SafePointBarrier::checkAndPark. | |
| 41 class SafePointAwareMutexLocker final { | |
| 42 STACK_ALLOCATED(); | |
| 43 WTF_MAKE_NONCOPYABLE(SafePointAwareMutexLocker); | |
| 44 | |
| 45 public: | |
| 46 explicit SafePointAwareMutexLocker( | |
| 47 MutexBase& mutex, | |
| 48 BlinkGC::StackState stackState = BlinkGC::HeapPointersOnStack) | |
| 49 : m_mutex(mutex), m_locked(false) { | |
| 50 ThreadState* state = ThreadState::current(); | |
| 51 do { | |
| 52 bool leaveSafePoint = false; | |
| 53 // We cannot enter a safepoint if we are currently sweeping. In that | |
| 54 // case we just try to acquire the lock without being at a safepoint. | |
| 55 // If another thread tries to do a GC at that time it might time out | |
| 56 // due to this thread not being at a safepoint and waiting on the lock. | |
| 57 if (!state->sweepForbidden() && !state->isAtSafePoint()) { | |
| 58 state->enterSafePoint(stackState, this); | |
| 59 leaveSafePoint = true; | |
| 60 } | |
| 61 m_mutex.lock(); | |
| 62 m_locked = true; | |
| 63 if (leaveSafePoint) { | |
| 64 // When leaving the safepoint we might end up release the mutex | |
| 65 // if another thread is requesting a GC, see | |
| 66 // SafePointBarrier::checkAndPark. This is the case where we | |
| 67 // loop around to reacquire the lock. | |
| 68 state->leaveSafePoint(this); | |
| 69 } | |
| 70 } while (!m_locked); | |
| 71 } | |
| 72 | |
| 73 ~SafePointAwareMutexLocker() { | |
| 74 ASSERT(m_locked); | |
| 75 m_mutex.unlock(); | |
| 76 } | |
| 77 | |
| 78 private: | |
| 79 friend class SafePointBarrier; | |
| 80 | |
| 81 void reset() { | |
| 82 ASSERT(m_locked); | |
| 83 m_mutex.unlock(); | |
| 84 m_locked = false; | |
| 85 } | |
| 86 | |
| 87 MutexBase& m_mutex; | |
| 88 bool m_locked; | |
| 89 }; | |
| 90 | |
| 91 class SafePointBarrier final { | 36 class SafePointBarrier final { |
| 92 USING_FAST_MALLOC(SafePointBarrier); | 37 USING_FAST_MALLOC(SafePointBarrier); |
| 93 WTF_MAKE_NONCOPYABLE(SafePointBarrier); | 38 WTF_MAKE_NONCOPYABLE(SafePointBarrier); |
| 94 | 39 |
| 95 public: | 40 public: |
| 96 SafePointBarrier(); | 41 SafePointBarrier(); |
| 97 ~SafePointBarrier(); | 42 ~SafePointBarrier(); |
| 98 | 43 |
| 99 void enterSafePoint(ThreadState*); | 44 void enterSafePoint(ThreadState*); |
| 100 void leaveSafePoint(ThreadState*, SafePointAwareMutexLocker* = nullptr); | 45 void leaveSafePoint(); |
| 101 | 46 |
| 102 private: | 47 private: |
| 103 void doPark(ThreadState*, intptr_t* stackEnd); | 48 void doPark(ThreadState*, intptr_t* stackEnd); |
| 104 void doEnterSafePoint(ThreadState*, intptr_t* stackEnd); | 49 void doEnterSafePoint(ThreadState*, intptr_t* stackEnd); |
| 105 static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, | 50 static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, |
| 106 ThreadState* state, | 51 ThreadState* state, |
| 107 intptr_t* stackEnd) { | 52 intptr_t* stackEnd) { |
| 108 barrier->doEnterSafePoint(state, stackEnd); | 53 barrier->doEnterSafePoint(state, stackEnd); |
| 109 } | 54 } |
| 110 Mutex m_mutex; | 55 Mutex m_mutex; |
| 111 }; | 56 }; |
| 112 | 57 |
| 113 } // namespace blink | 58 } // namespace blink |
| 114 | 59 |
| 115 #endif | 60 #endif |
| OLD | NEW |