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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 #error Unsupported getStackStart on this platform. | 89 #error Unsupported getStackStart on this platform. |
90 #endif | 90 #endif |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = 0; | 94 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = 0; |
95 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; | 95 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; |
96 SafePointBarrier* ThreadState::s_safePointBarrier = 0; | 96 SafePointBarrier* ThreadState::s_safePointBarrier = 0; |
97 bool ThreadState::s_inGC = false; | 97 bool ThreadState::s_inGC = false; |
98 | 98 |
99 static Mutex& threadAttachMutex() | 99 Mutex& ThreadState::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 500 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) { } |
118 ~SafePointBarrier() { } | 118 ~SafePointBarrier() { } |
119 | 119 |
120 // Request other attached threads that are not at safe points to park themse
lves on safepoints. | 120 // Request other attached threads that are not at safe points to park themse
lves on safepoints. |
121 bool parkOthers() | 121 bool parkOthers() |
122 { | 122 { |
123 ASSERT(ThreadState::current()->isAtSafePoint()); | 123 ASSERT(ThreadState::current()->isAtSafePoint()); |
124 | 124 |
125 // Lock threadAttachMutex() to prevent threads from attaching. | 125 // Lock threadAttachMutex() to prevent threads from attaching. |
126 threadAttachMutex().lock(); | 126 ThreadState::threadAttachMutex().lock(); |
127 | 127 |
128 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre
ads(); | 128 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre
ads(); |
129 | 129 |
130 MutexLocker locker(m_mutex); | 130 MutexLocker locker(m_mutex); |
131 atomicAdd(&m_unparkedThreadCount, threads.size()); | 131 atomicAdd(&m_unparkedThreadCount, threads.size()); |
132 releaseStore(&m_canResume, 0); | 132 releaseStore(&m_canResume, 0); |
133 | 133 |
134 ThreadState* current = ThreadState::current(); | 134 ThreadState* current = ThreadState::current(); |
135 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(),
end = threads.end(); it != end; ++it) { | 135 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(),
end = threads.end(); it != end; ++it) { |
136 if (*it == current) | 136 if (*it == current) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 ThreadState* current = ThreadState::current(); | 175 ThreadState* current = ThreadState::current(); |
176 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(),
end = threads.end(); it != end; ++it) { | 176 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(),
end = threads.end(); it != end; ++it) { |
177 if (*it == current) | 177 if (*it == current) |
178 continue; | 178 continue; |
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 ThreadState::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) |
190 { | 190 { |
191 ASSERT(!state->isSweepInProgress()); | 191 ASSERT(!state->isSweepInProgress()); |
192 if (!acquireLoad(&m_canResume)) { | 192 if (!acquireLoad(&m_canResume)) { |
193 pushAllRegisters(this, state, parkAfterPushRegisters); | 193 pushAllRegisters(this, state, parkAfterPushRegisters); |
194 state->performPendingSweep(); | 194 state->performPendingSweep(); |
195 } | 195 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 { | 308 { |
309 delete s_safePointBarrier; | 309 delete s_safePointBarrier; |
310 s_safePointBarrier = 0; | 310 s_safePointBarrier = 0; |
311 | 311 |
312 // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpeci
fic(). | 312 // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpeci
fic(). |
313 } | 313 } |
314 | 314 |
315 void ThreadState::attachMainThread() | 315 void ThreadState::attachMainThread() |
316 { | 316 { |
317 RELEASE_ASSERT(!Heap::s_shutdownCalled); | 317 RELEASE_ASSERT(!Heap::s_shutdownCalled); |
318 MutexLocker locker(threadAttachMutex()); | 318 MutexLocker locker(ThreadState::threadAttachMutex()); |
319 ThreadState* state = new(s_mainThreadStateStorage) ThreadState(); | 319 ThreadState* state = new(s_mainThreadStateStorage) ThreadState(); |
320 attachedThreads().add(state); | 320 attachedThreads().add(state); |
321 } | 321 } |
322 | 322 |
323 void ThreadState::detachMainThread() | 323 void ThreadState::detachMainThread() |
324 { | 324 { |
325 // Enter a safe point before trying to acquire threadAttachMutex | 325 // Enter a safe point before trying to acquire threadAttachMutex |
326 // to avoid dead lock if another thread is preparing for GC, has acquired | 326 // to avoid dead lock if another thread is preparing for GC, has acquired |
327 // threadAttachMutex and waiting for other threads to pause or reach a | 327 // threadAttachMutex and waiting for other threads to pause or reach a |
328 // safepoint. | 328 // safepoint. |
329 ThreadState* state = mainThreadState(); | 329 ThreadState* state = mainThreadState(); |
330 if (!state->isAtSafePoint()) | 330 if (!state->isAtSafePoint()) |
331 state->enterSafePointWithoutPointers(); | 331 state->enterSafePointWithoutPointers(); |
332 | 332 |
333 { | 333 { |
334 MutexLocker locker(threadAttachMutex()); | 334 MutexLocker locker(ThreadState::threadAttachMutex()); |
335 state->leaveSafePoint(); | 335 state->leaveSafePoint(); |
336 ASSERT(attachedThreads().contains(state)); | 336 ASSERT(attachedThreads().contains(state)); |
337 attachedThreads().remove(state); | 337 attachedThreads().remove(state); |
338 state->~ThreadState(); | 338 state->~ThreadState(); |
339 } | 339 } |
340 shutdownHeapIfNecessary(); | 340 shutdownHeapIfNecessary(); |
341 } | 341 } |
342 | 342 |
343 void ThreadState::shutdownHeapIfNecessary() | 343 void ThreadState::shutdownHeapIfNecessary() |
344 { | 344 { |
345 // We don't need to enter a safe point before acquiring threadAttachMutex | 345 // We don't need to enter a safe point before acquiring threadAttachMutex |
346 // because this thread is already detached. | 346 // because this thread is already detached. |
347 | 347 |
348 MutexLocker locker(threadAttachMutex()); | 348 MutexLocker locker(ThreadState::threadAttachMutex()); |
349 // We start shutting down the heap if there is no running thread | 349 // We start shutting down the heap if there is no running thread |
350 // and Heap::shutdown() is already called. | 350 // and Heap::shutdown() is already called. |
351 if (!attachedThreads().size() && Heap::s_shutdownCalled) | 351 if (!attachedThreads().size() && Heap::s_shutdownCalled) |
352 Heap::doShutdown(); | 352 Heap::doShutdown(); |
353 } | 353 } |
354 | 354 |
355 void ThreadState::attach() | 355 void ThreadState::attach() |
356 { | 356 { |
357 RELEASE_ASSERT(!Heap::s_shutdownCalled); | 357 RELEASE_ASSERT(!Heap::s_shutdownCalled); |
358 MutexLocker locker(threadAttachMutex()); | 358 MutexLocker locker(ThreadState::threadAttachMutex()); |
359 ThreadState* state = new ThreadState(); | 359 ThreadState* state = new ThreadState(); |
360 attachedThreads().add(state); | 360 attachedThreads().add(state); |
361 } | 361 } |
362 | 362 |
363 void ThreadState::cleanup() | 363 void ThreadState::cleanup() |
364 { | 364 { |
365 // From here on ignore all conservatively discovered | 365 // From here on ignore all conservatively discovered |
366 // pointers into the heap owned by this thread. | 366 // pointers into the heap owned by this thread. |
367 m_isCleaningUp = true; | 367 m_isCleaningUp = true; |
368 | 368 |
(...skipping 21 matching lines...) Expand all Loading... |
390 state->cleanup(); | 390 state->cleanup(); |
391 | 391 |
392 // Enter a safe point before trying to acquire threadAttachMutex | 392 // Enter a safe point before trying to acquire threadAttachMutex |
393 // to avoid dead lock if another thread is preparing for GC, has acquired | 393 // to avoid dead lock if another thread is preparing for GC, has acquired |
394 // threadAttachMutex and waiting for other threads to pause or reach a | 394 // threadAttachMutex and waiting for other threads to pause or reach a |
395 // safepoint. | 395 // safepoint. |
396 if (!state->isAtSafePoint()) | 396 if (!state->isAtSafePoint()) |
397 state->enterSafePointWithoutPointers(); | 397 state->enterSafePointWithoutPointers(); |
398 | 398 |
399 { | 399 { |
400 MutexLocker locker(threadAttachMutex()); | 400 MutexLocker locker(ThreadState::threadAttachMutex()); |
401 state->leaveSafePoint(); | 401 state->leaveSafePoint(); |
402 ASSERT(attachedThreads().contains(state)); | 402 ASSERT(attachedThreads().contains(state)); |
403 attachedThreads().remove(state); | 403 attachedThreads().remove(state); |
404 delete state; | 404 delete state; |
405 } | 405 } |
406 shutdownHeapIfNecessary(); | 406 shutdownHeapIfNecessary(); |
407 } | 407 } |
408 | 408 |
409 void ThreadState::visitRoots(Visitor* visitor) | 409 void ThreadState::visitRoots(Visitor* visitor) |
410 { | 410 { |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 | 853 |
854 if (isMainThread()) | 854 if (isMainThread()) |
855 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); | 855 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); |
856 } | 856 } |
857 | 857 |
858 void ThreadState::addInterruptor(Interruptor* interruptor) | 858 void ThreadState::addInterruptor(Interruptor* interruptor) |
859 { | 859 { |
860 SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); | 860 SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); |
861 | 861 |
862 { | 862 { |
863 MutexLocker locker(threadAttachMutex()); | 863 MutexLocker locker(ThreadState::threadAttachMutex()); |
864 m_interruptors.append(interruptor); | 864 m_interruptors.append(interruptor); |
865 } | 865 } |
866 } | 866 } |
867 | 867 |
868 void ThreadState::removeInterruptor(Interruptor* interruptor) | 868 void ThreadState::removeInterruptor(Interruptor* interruptor) |
869 { | 869 { |
870 SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); | 870 SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); |
871 | 871 |
872 { | 872 { |
873 MutexLocker locker(threadAttachMutex()); | 873 MutexLocker locker(ThreadState::threadAttachMutex()); |
874 size_t index = m_interruptors.find(interruptor); | 874 size_t index = m_interruptors.find(interruptor); |
875 RELEASE_ASSERT(index >= 0); | 875 RELEASE_ASSERT(index >= 0); |
876 m_interruptors.remove(index); | 876 m_interruptors.remove(index); |
877 } | 877 } |
878 } | 878 } |
879 | 879 |
880 void ThreadState::Interruptor::onInterrupted() | 880 void ThreadState::Interruptor::onInterrupted() |
881 { | 881 { |
882 ThreadState* state = ThreadState::current(); | 882 ThreadState* state = ThreadState::current(); |
883 ASSERT(state); | 883 ASSERT(state); |
884 ASSERT(!state->isAtSafePoint()); | 884 ASSERT(!state->isAtSafePoint()); |
885 state->safePoint(HeapPointersOnStack); | 885 state->safePoint(HeapPointersOnStack); |
886 } | 886 } |
887 | 887 |
888 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() | 888 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
889 { | 889 { |
890 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); | 890 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
891 return threads; | 891 return threads; |
892 } | 892 } |
893 | 893 |
894 } | 894 } |
OLD | NEW |