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 |