| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 bool ThreadState::s_inGC = false; | 97 bool ThreadState::s_inGC = false; |
| 98 | 98 |
| 99 static Mutex& threadAttachMutex() | 99 static Mutex& threadAttachMutex() |
| 100 { | 100 { |
| 101 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); | 101 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); |
| 102 return mutex; | 102 return mutex; |
| 103 } | 103 } |
| 104 | 104 |
| 105 static double lockingTimeout() | 105 static double lockingTimeout() |
| 106 { | 106 { |
| 107 // Wait time for parking all threads is at most 500 MS. | 107 // Wait time for parking all threads is at most 100 MS. |
| 108 return 0.100; | 108 return 0.100; |
| 109 } | 109 } |
| 110 | 110 |
| 111 | 111 |
| 112 typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr
_t*); | 112 typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr
_t*); |
| 113 extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegiste
rsCallback); | 113 extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegiste
rsCallback); |
| 114 | 114 |
| 115 class SafePointBarrier { | 115 class SafePointBarrier { |
| 116 public: | 116 public: |
| 117 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { } | 117 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 | 179 |
| 180 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter
ruptors(); | 180 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter
ruptors(); |
| 181 for (size_t i = 0; i < interruptors.size(); i++) | 181 for (size_t i = 0; i < interruptors.size(); i++) |
| 182 interruptors[i]->clearInterrupt(); | 182 interruptors[i]->clearInterrupt(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 threadAttachMutex().unlock(); | 185 threadAttachMutex().unlock(); |
| 186 ASSERT(ThreadState::current()->isAtSafePoint()); | 186 ASSERT(ThreadState::current()->isAtSafePoint()); |
| 187 } | 187 } |
| 188 | 188 |
| 189 void checkAndPark(ThreadState* state) | 189 void checkAndPark(ThreadState* state, SafePointAwareMutexLocker* locker = 0) |
| 190 { | 190 { |
| 191 ASSERT(!state->isSweepInProgress()); | 191 ASSERT(!state->isSweepInProgress()); |
| 192 if (!acquireLoad(&m_canResume)) { | 192 if (!acquireLoad(&m_canResume)) { |
| 193 // If we are leaving the safepoint from a SafePointAwareMutexLocker |
| 194 // call out to release the lock before going to sleep. This enables
the |
| 195 // lock to be acquired in the sweep phase, e.g. during weak processi
ng |
| 196 // or finalization. The SafePointAwareLocker will reenter the safepo
int |
| 197 // and reacquire the lock after leaving this safepoint. |
| 198 if (locker) |
| 199 locker->reset(); |
| 193 pushAllRegisters(this, state, parkAfterPushRegisters); | 200 pushAllRegisters(this, state, parkAfterPushRegisters); |
| 194 state->performPendingSweep(); | 201 state->performPendingSweep(); |
| 195 } | 202 } |
| 196 } | 203 } |
| 197 | 204 |
| 198 void enterSafePoint(ThreadState* state) | 205 void enterSafePoint(ThreadState* state) |
| 199 { | 206 { |
| 200 ASSERT(!state->isSweepInProgress()); | 207 ASSERT(!state->isSweepInProgress()); |
| 201 pushAllRegisters(this, state, enterSafePointAfterPushRegisters); | 208 pushAllRegisters(this, state, enterSafePointAfterPushRegisters); |
| 202 } | 209 } |
| 203 | 210 |
| 204 void leaveSafePoint(ThreadState* state) | 211 void leaveSafePoint(ThreadState* state, SafePointAwareMutexLocker* locker =
0) |
| 205 { | 212 { |
| 206 if (atomicIncrement(&m_unparkedThreadCount) > 0) | 213 if (atomicIncrement(&m_unparkedThreadCount) > 0) |
| 207 checkAndPark(state); | 214 checkAndPark(state, locker); |
| 208 } | 215 } |
| 209 | 216 |
| 210 private: | 217 private: |
| 211 void doPark(ThreadState* state, intptr_t* stackEnd) | 218 void doPark(ThreadState* state, intptr_t* stackEnd) |
| 212 { | 219 { |
| 213 state->recordStackEnd(stackEnd); | 220 state->recordStackEnd(stackEnd); |
| 214 MutexLocker locker(m_mutex); | 221 MutexLocker locker(m_mutex); |
| 215 if (!atomicDecrement(&m_unparkedThreadCount)) | 222 if (!atomicDecrement(&m_unparkedThreadCount)) |
| 216 m_parked.signal(); | 223 m_parked.signal(); |
| 217 while (!acquireLoad(&m_canResume)) | 224 while (!acquireLoad(&m_canResume)) |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 | 745 |
| 739 void ThreadState::resumeThreads() | 746 void ThreadState::resumeThreads() |
| 740 { | 747 { |
| 741 s_safePointBarrier->resumeOthers(); | 748 s_safePointBarrier->resumeOthers(); |
| 742 } | 749 } |
| 743 | 750 |
| 744 void ThreadState::safePoint(StackState stackState) | 751 void ThreadState::safePoint(StackState stackState) |
| 745 { | 752 { |
| 746 checkThread(); | 753 checkThread(); |
| 747 performPendingGC(stackState); | 754 performPendingGC(stackState); |
| 755 ASSERT(!m_atSafePoint); |
| 748 m_stackState = stackState; | 756 m_stackState = stackState; |
| 757 m_atSafePoint = true; |
| 749 s_safePointBarrier->checkAndPark(this); | 758 s_safePointBarrier->checkAndPark(this); |
| 759 m_atSafePoint = false; |
| 750 m_stackState = HeapPointersOnStack; | 760 m_stackState = HeapPointersOnStack; |
| 751 } | 761 } |
| 752 | 762 |
| 753 #ifdef ADDRESS_SANITIZER | 763 #ifdef ADDRESS_SANITIZER |
| 754 // When we are running under AddressSanitizer with detect_stack_use_after_return
=1 | 764 // When we are running under AddressSanitizer with detect_stack_use_after_return
=1 |
| 755 // then stack marker obtained from SafePointScope will point into a fake stack. | 765 // then stack marker obtained from SafePointScope will point into a fake stack. |
| 756 // Detect this case by checking if it falls in between current stack frame | 766 // Detect this case by checking if it falls in between current stack frame |
| 757 // and stack start and use an arbitrary high enough value for it. | 767 // and stack start and use an arbitrary high enough value for it. |
| 758 // Don't adjust stack marker in any other case to match behavior of code running | 768 // Don't adjust stack marker in any other case to match behavior of code running |
| 759 // without AddressSanitizer. | 769 // without AddressSanitizer. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 784 ASSERT(stackState == NoHeapPointersOnStack || scopeMarker); | 794 ASSERT(stackState == NoHeapPointersOnStack || scopeMarker); |
| 785 performPendingGC(stackState); | 795 performPendingGC(stackState); |
| 786 checkThread(); | 796 checkThread(); |
| 787 ASSERT(!m_atSafePoint); | 797 ASSERT(!m_atSafePoint); |
| 788 m_atSafePoint = true; | 798 m_atSafePoint = true; |
| 789 m_stackState = stackState; | 799 m_stackState = stackState; |
| 790 m_safePointScopeMarker = scopeMarker; | 800 m_safePointScopeMarker = scopeMarker; |
| 791 s_safePointBarrier->enterSafePoint(this); | 801 s_safePointBarrier->enterSafePoint(this); |
| 792 } | 802 } |
| 793 | 803 |
| 794 void ThreadState::leaveSafePoint() | 804 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) |
| 795 { | 805 { |
| 796 checkThread(); | 806 checkThread(); |
| 797 ASSERT(m_atSafePoint); | 807 ASSERT(m_atSafePoint); |
| 798 s_safePointBarrier->leaveSafePoint(this); | 808 s_safePointBarrier->leaveSafePoint(this, locker); |
| 799 m_atSafePoint = false; | 809 m_atSafePoint = false; |
| 800 m_stackState = HeapPointersOnStack; | 810 m_stackState = HeapPointersOnStack; |
| 801 clearSafePointScopeMarker(); | 811 clearSafePointScopeMarker(); |
| 802 performPendingSweep(); | 812 performPendingSweep(); |
| 803 } | 813 } |
| 804 | 814 |
| 805 void ThreadState::copyStackUntilSafePointScope() | 815 void ThreadState::copyStackUntilSafePointScope() |
| 806 { | 816 { |
| 807 if (!m_safePointScopeMarker || m_stackState == NoHeapPointersOnStack) | 817 if (!m_safePointScopeMarker || m_stackState == NoHeapPointersOnStack) |
| 808 return; | 818 return; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 threadAttachMutex().unlock(); | 915 threadAttachMutex().unlock(); |
| 906 return gcInfo; | 916 return gcInfo; |
| 907 } | 917 } |
| 908 } | 918 } |
| 909 if (needLockForIteration) | 919 if (needLockForIteration) |
| 910 threadAttachMutex().unlock(); | 920 threadAttachMutex().unlock(); |
| 911 return 0; | 921 return 0; |
| 912 } | 922 } |
| 913 #endif | 923 #endif |
| 914 } | 924 } |
| OLD | NEW |