| 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 |