Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: Source/platform/heap/ThreadState.cpp

Issue 311263008: Make |Heap::findGCInfo()| threadsafe. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: change check to isAnyThreadInGC Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« Source/platform/heap/ThreadState.h ('K') | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698