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

Side by Side Diff: sky/engine/platform/heap/ThreadState.cpp

Issue 678003003: Begin to remove heap/* (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month 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
« no previous file with comments | « sky/engine/platform/heap/ThreadState.h ('k') | sky/engine/platform/testing/RunAllTests.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; 90 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
91 SafePointBarrier* ThreadState::s_safePointBarrier = 0; 91 SafePointBarrier* ThreadState::s_safePointBarrier = 0;
92 bool ThreadState::s_inGC = false; 92 bool ThreadState::s_inGC = false;
93 93
94 static Mutex& threadAttachMutex() 94 static Mutex& threadAttachMutex()
95 { 95 {
96 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 96 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
97 return mutex; 97 return mutex;
98 } 98 }
99 99
100 static double lockingTimeout()
101 {
102 // Wait time for parking all threads is at most 100 MS.
103 return 0.100;
104 }
105
106
107 typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr _t*);
108 extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegiste rsCallback);
109
110 class SafePointBarrier { 100 class SafePointBarrier {
111 public: 101 public:
112 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { } 102 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { }
113 ~SafePointBarrier() { } 103 ~SafePointBarrier() { }
114 104
115 // Request other attached threads that are not at safe points to park themse lves on safepoints. 105 // Request other attached threads that are not at safe points to park themse lves on safepoints.
116 bool parkOthers() 106 bool parkOthers()
117 { 107 {
118 ASSERT(ThreadState::current()->isAtSafePoint());
119
120 // Lock threadAttachMutex() to prevent threads from attaching.
121 threadAttachMutex().lock();
122
123 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads();
124
125 MutexLocker locker(m_mutex);
126 atomicAdd(&m_unparkedThreadCount, threads.size());
127 releaseStore(&m_canResume, 0);
128
129 ThreadState* current = ThreadState::current();
130 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
131 if (*it == current)
132 continue;
133
134 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors();
135 for (size_t i = 0; i < interruptors.size(); i++)
136 interruptors[i]->requestInterrupt();
137 }
138
139 while (acquireLoad(&m_unparkedThreadCount) > 0) {
140 double expirationTime = currentTime() + lockingTimeout();
141 if (!m_parked.timedWait(m_mutex, expirationTime)) {
142 // One of the other threads did not return to a safepoint within the maximum
143 // time we allow for threads to be parked. Abandon the GC and re sume the
144 // currently parked threads.
145 resumeOthers(true);
146 return false;
147 }
148 }
149 return true; 108 return true;
150 } 109 }
151 110
152 void resumeOthers(bool barrierLocked = false) 111 void resumeOthers(bool barrierLocked = false)
153 { 112 {
154 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads();
155 atomicSubtract(&m_unparkedThreadCount, threads.size());
156 releaseStore(&m_canResume, 1);
157
158 // FIXME: Resumed threads will all contend for m_mutex just to unlock it
159 // later which is a waste of resources.
160 if (UNLIKELY(barrierLocked)) {
161 m_resume.broadcast();
162 } else {
163 // FIXME: Resumed threads will all contend for
164 // m_mutex just to unlock it later which is a waste of
165 // resources.
166 MutexLocker locker(m_mutex);
167 m_resume.broadcast();
168 }
169
170 ThreadState* current = ThreadState::current();
171 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
172 if (*it == current)
173 continue;
174
175 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors();
176 for (size_t i = 0; i < interruptors.size(); i++)
177 interruptors[i]->clearInterrupt();
178 }
179
180 threadAttachMutex().unlock();
181 ASSERT(ThreadState::current()->isAtSafePoint());
182 } 113 }
183 114
184 void checkAndPark(ThreadState* state, SafePointAwareMutexLocker* locker = 0) 115 void checkAndPark(ThreadState* state, SafePointAwareMutexLocker* locker = 0)
185 { 116 {
186 ASSERT(!state->isSweepInProgress());
187 if (!acquireLoad(&m_canResume)) {
188 // If we are leaving the safepoint from a SafePointAwareMutexLocker
189 // call out to release the lock before going to sleep. This enables the
190 // lock to be acquired in the sweep phase, e.g. during weak processi ng
191 // or finalization. The SafePointAwareLocker will reenter the safepo int
192 // and reacquire the lock after leaving this safepoint.
193 if (locker)
194 locker->reset();
195 pushAllRegisters(this, state, parkAfterPushRegisters);
196 }
197 } 117 }
198 118
199 void enterSafePoint(ThreadState* state) 119 void enterSafePoint(ThreadState* state)
200 { 120 {
201 ASSERT(!state->isSweepInProgress());
202 pushAllRegisters(this, state, enterSafePointAfterPushRegisters);
203 } 121 }
204 122
205 void leaveSafePoint(ThreadState* state, SafePointAwareMutexLocker* locker = 0) 123 void leaveSafePoint(ThreadState* state, SafePointAwareMutexLocker* locker = 0)
206 { 124 {
207 if (atomicIncrement(&m_unparkedThreadCount) > 0)
208 checkAndPark(state, locker);
209 } 125 }
210 126
211 private: 127 private:
212 void doPark(ThreadState* state, intptr_t* stackEnd) 128 void doPark(ThreadState* state, intptr_t* stackEnd)
213 { 129 {
214 state->recordStackEnd(stackEnd); 130 state->recordStackEnd(stackEnd);
215 MutexLocker locker(m_mutex); 131 MutexLocker locker(m_mutex);
216 if (!atomicDecrement(&m_unparkedThreadCount)) 132 if (!atomicDecrement(&m_unparkedThreadCount))
217 m_parked.signal(); 133 m_parked.signal();
218 while (!acquireLoad(&m_canResume)) 134 while (!acquireLoad(&m_canResume))
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m _liveWrapperPersistents); 239 WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m _liveWrapperPersistents);
324 delete region; 240 delete region;
325 } 241 }
326 while (m_pooledWrapperPersistents) { 242 while (m_pooledWrapperPersistents) {
327 WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m _pooledWrapperPersistents); 243 WrapperPersistentRegion* region = WrapperPersistentRegion::removeHead(&m _pooledWrapperPersistents);
328 delete region; 244 delete region;
329 } 245 }
330 **s_threadSpecific = 0; 246 **s_threadSpecific = 0;
331 } 247 }
332 248
333 void ThreadState::init()
334 {
335 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>();
336 s_safePointBarrier = new SafePointBarrier;
337 }
338
339 void ThreadState::shutdown()
340 {
341 delete s_safePointBarrier;
342 s_safePointBarrier = 0;
343
344 // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpeci fic().
345 }
346
347 void ThreadState::attachMainThread()
348 {
349 RELEASE_ASSERT(!Heap::s_shutdownCalled);
350 MutexLocker locker(threadAttachMutex());
351 ThreadState* state = new(s_mainThreadStateStorage) ThreadState();
352 attachedThreads().add(state);
353 }
354
355 void ThreadState::detachMainThread()
356 {
357 // Enter a safe point before trying to acquire threadAttachMutex
358 // to avoid dead lock if another thread is preparing for GC, has acquired
359 // threadAttachMutex and waiting for other threads to pause or reach a
360 // safepoint.
361 ThreadState* state = mainThreadState();
362
363 {
364 SafePointAwareMutexLocker locker(threadAttachMutex(), NoHeapPointersOnSt ack);
365
366 // First add the main thread's heap pages to the orphaned pool.
367 state->cleanupPages();
368
369 // Second detach thread.
370 ASSERT(attachedThreads().contains(state));
371 attachedThreads().remove(state);
372 state->~ThreadState();
373 }
374 shutdownHeapIfNecessary();
375 }
376
377 void ThreadState::shutdownHeapIfNecessary()
378 {
379 // We don't need to enter a safe point before acquiring threadAttachMutex
380 // because this thread is already detached.
381
382 MutexLocker locker(threadAttachMutex());
383 // We start shutting down the heap if there is no running thread
384 // and Heap::shutdown() is already called.
385 if (!attachedThreads().size() && Heap::s_shutdownCalled)
386 Heap::doShutdown();
387 }
388
389 void ThreadState::attach() 249 void ThreadState::attach()
390 { 250 {
391 RELEASE_ASSERT(!Heap::s_shutdownCalled); 251 RELEASE_ASSERT(!Heap::s_shutdownCalled);
392 MutexLocker locker(threadAttachMutex()); 252 MutexLocker locker(threadAttachMutex());
393 ThreadState* state = new ThreadState(); 253 ThreadState* state = new ThreadState();
394 attachedThreads().add(state); 254 attachedThreads().add(state);
395 } 255 }
396 256
397 void ThreadState::cleanupPages() 257 void ThreadState::cleanupPages()
398 { 258 {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 ASSERT(attachedThreads().contains(this)); 305 ASSERT(attachedThreads().contains(this));
446 attachedThreads().remove(this); 306 attachedThreads().remove(this);
447 } 307 }
448 308
449 for (size_t i = 0; i < m_cleanupTasks.size(); i++) 309 for (size_t i = 0; i < m_cleanupTasks.size(); i++)
450 m_cleanupTasks[i]->postCleanup(); 310 m_cleanupTasks[i]->postCleanup();
451 m_cleanupTasks.clear(); 311 m_cleanupTasks.clear();
452 } 312 }
453 313
454 314
455 void ThreadState::detach()
456 {
457 ThreadState* state = current();
458 state->cleanup();
459 delete state;
460 shutdownHeapIfNecessary();
461 }
462
463 void ThreadState::visitPersistentRoots(Visitor* visitor) 315 void ThreadState::visitPersistentRoots(Visitor* visitor)
464 { 316 {
465 { 317 {
466 // All threads are at safepoints so this is not strictly necessary. 318 // All threads are at safepoints so this is not strictly necessary.
467 // However we acquire the mutex to make mutation and traversal of this 319 // However we acquire the mutex to make mutation and traversal of this
468 // list symmetrical. 320 // list symmetrical.
469 MutexLocker locker(globalRootsMutex()); 321 MutexLocker locker(globalRootsMutex());
470 globalRoots()->trace(visitor); 322 globalRoots()->trace(visitor);
471 } 323 }
472 324
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 return gcInfo; 933 return gcInfo;
1082 } 934 }
1083 } 935 }
1084 if (needLockForIteration) 936 if (needLockForIteration)
1085 threadAttachMutex().unlock(); 937 threadAttachMutex().unlock();
1086 return 0; 938 return 0;
1087 } 939 }
1088 #endif 940 #endif
1089 941
1090 } 942 }
OLDNEW
« no previous file with comments | « sky/engine/platform/heap/ThreadState.h ('k') | sky/engine/platform/testing/RunAllTests.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698