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

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

Issue 260723003: [oilpan]: Make parking threads for GC timeout in the case parking exceeds 100 MS (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 7 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
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; 89 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
90 SafePointBarrier* ThreadState::s_safePointBarrier = 0; 90 SafePointBarrier* ThreadState::s_safePointBarrier = 0;
91 bool ThreadState::s_inGC = false; 91 bool ThreadState::s_inGC = false;
92 92
93 static Mutex& threadAttachMutex() 93 static Mutex& threadAttachMutex()
94 { 94 {
95 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 95 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
96 return mutex; 96 return mutex;
97 } 97 }
98 98
99 static double lockingTimeout()
100 {
101 // Wait time for parking all threads is at most 10 MS.
102 return 0.01;
103 }
104
105
99 typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr _t*); 106 typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr _t*);
100 extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegiste rsCallback); 107 extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegiste rsCallback);
101 108
102 class SafePointBarrier { 109 class SafePointBarrier {
103 public: 110 public:
104 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { } 111 SafePointBarrier() : m_canResume(1), m_unparkedThreadCount(0) { }
105 ~SafePointBarrier() { } 112 ~SafePointBarrier() { }
106 113
107 // Request other attached threads that are not at safe points to park themse lves on safepoints. 114 // Request other attached threads that are not at safe points to park themse lves on safepoints.
108 void parkOthers() 115 bool parkOthers()
109 { 116 {
110 ASSERT(ThreadState::current()->isAtSafePoint()); 117 ASSERT(ThreadState::current()->isAtSafePoint());
111 118
112 // Lock threadAttachMutex() to prevent threads from attaching. 119 // Lock threadAttachMutex() to prevent threads from attaching.
113 threadAttachMutex().lock(); 120 threadAttachMutex().lock();
114 121
115 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads(); 122 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads();
116 123
117 MutexLocker locker(m_mutex); 124 MutexLocker locker(m_mutex);
118 atomicAdd(&m_unparkedThreadCount, threads.size()); 125 atomicAdd(&m_unparkedThreadCount, threads.size());
119 releaseStore(&m_canResume, 0); 126 releaseStore(&m_canResume, 0);
120 127
121 ThreadState* current = ThreadState::current(); 128 ThreadState* current = ThreadState::current();
122 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 129 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
123 if (*it == current) 130 if (*it == current)
124 continue; 131 continue;
125 132
126 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors(); 133 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors();
127 for (size_t i = 0; i < interruptors.size(); i++) 134 for (size_t i = 0; i < interruptors.size(); i++)
128 interruptors[i]->requestInterrupt(); 135 interruptors[i]->requestInterrupt();
129 } 136 }
130 137
131 while (acquireLoad(&m_unparkedThreadCount) > 0) 138 while (acquireLoad(&m_unparkedThreadCount) > 0) {
132 m_parked.wait(m_mutex); 139 double expirationTime = currentTime() + lockingTimeout();
140 if (!m_parked.timedWait(m_mutex, expirationTime)) {
141 // One of the other threads did not return to a safepoint within the maximum
142 // time we allow for threads to be parked. Abandon the GC and re sume the
143 // currently parked threads.
144 resumeOthers(true);
haraken 2014/05/01 04:03:56 Nit: It would be more consistent if you can remove
wibling-chromium 2014/05/01 06:51:48 Yes, that would be nice. However I am worried that
haraken 2014/05/01 07:33:50 Yes, but is it problematic that we allow another t
wibling-chromium 2014/05/01 08:25:18 No, that should be okay. However previously we wou
haraken 2014/05/01 08:36:31 Thanks for the clarification, makes sense!
145 return false;
146 }
147 }
148 return true;
133 } 149 }
134 150
135 void resumeOthers() 151 void resumeOthers(bool barrierLocked = false)
136 { 152 {
137 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads(); 153 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThre ads();
138 atomicSubtract(&m_unparkedThreadCount, threads.size()); 154 atomicSubtract(&m_unparkedThreadCount, threads.size());
haraken 2014/05/01 04:03:56 I guess this will confuse m_unparkedThreadCount. A
wibling-chromium 2014/05/01 06:51:48 I initially read the code the same way, but parkOt
haraken 2014/05/01 07:33:50 Thanks for the clarification. Your explanation sou
139 releaseStore(&m_canResume, 1); 155 releaseStore(&m_canResume, 1);
140 { 156
157 // FIXME: Resumed threads will all contend for m_mutex just to unlock it
158 // later which is a waste of resources.
159 if (UNLIKELY(barrierLocked)) {
160 m_resume.broadcast();
161 } else {
141 // FIXME: Resumed threads will all contend for 162 // FIXME: Resumed threads will all contend for
142 // m_mutex just to unlock it later which is a waste of 163 // m_mutex just to unlock it later which is a waste of
143 // resources. 164 // resources.
144 MutexLocker locker(m_mutex); 165 MutexLocker locker(m_mutex);
145 m_resume.broadcast(); 166 m_resume.broadcast();
146 } 167 }
147 168
148 ThreadState* current = ThreadState::current(); 169 ThreadState* current = ThreadState::current();
149 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 170 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
150 if (*it == current) 171 if (*it == current)
151 continue; 172 continue;
152 173
153 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors(); 174 const Vector<ThreadState::Interruptor*>& interruptors = (*it)->inter ruptors();
154 for (size_t i = 0; i < interruptors.size(); i++) 175 for (size_t i = 0; i < interruptors.size(); i++)
155 interruptors[i]->clearInterrupt(); 176 interruptors[i]->clearInterrupt();
156 } 177 }
157 178
158 threadAttachMutex().unlock(); 179 threadAttachMutex().unlock();
159 ASSERT(ThreadState::current()->isAtSafePoint()); 180 ASSERT(ThreadState::current()->isAtSafePoint());
160 } 181 }
161 182
183 void checkAndPark(ThreadState* state)
zerny-chromium 2014/05/01 07:05:38 Nit: avoid reordering/formatting for unchanged cod
wibling-chromium 2014/05/01 08:25:18 Done. I will revert that and do it in a separate c
184 {
185 ASSERT(!state->isSweepInProgress());
186 if (!acquireLoad(&m_canResume)) {
187 pushAllRegisters(this, state, parkAfterPushRegisters);
188 state->performPendingSweep();
189 }
190 }
191
192 void enterSafePoint(ThreadState* state)
193 {
194 ASSERT(!state->isSweepInProgress());
195 pushAllRegisters(this, state, enterSafePointAfterPushRegisters);
196 }
197
198 void leaveSafePoint(ThreadState* state)
199 {
200 if (atomicIncrement(&m_unparkedThreadCount) > 0)
201 checkAndPark(state);
202 }
203
204 private:
162 void doPark(ThreadState* state, intptr_t* stackEnd) 205 void doPark(ThreadState* state, intptr_t* stackEnd)
163 { 206 {
164 state->recordStackEnd(stackEnd); 207 state->recordStackEnd(stackEnd);
165 MutexLocker locker(m_mutex); 208 MutexLocker locker(m_mutex);
166 if (!atomicDecrement(&m_unparkedThreadCount)) 209 if (!atomicDecrement(&m_unparkedThreadCount))
167 m_parked.signal(); 210 m_parked.signal();
168 while (!acquireLoad(&m_canResume)) 211 while (!acquireLoad(&m_canResume))
169 m_resume.wait(m_mutex); 212 m_resume.wait(m_mutex);
170 atomicIncrement(&m_unparkedThreadCount); 213 atomicIncrement(&m_unparkedThreadCount);
171 } 214 }
172 215
173 void checkAndPark(ThreadState* state) 216 static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* s tate, intptr_t* stackEnd)
174 { 217 {
175 ASSERT(!state->isSweepInProgress()); 218 barrier->doPark(state, stackEnd);
176 if (!acquireLoad(&m_canResume)) {
177 pushAllRegisters(this, state, parkAfterPushRegisters);
178 state->performPendingSweep();
179 }
180 } 219 }
181 220
182 void doEnterSafePoint(ThreadState* state, intptr_t* stackEnd) 221 void doEnterSafePoint(ThreadState* state, intptr_t* stackEnd)
183 { 222 {
184 state->recordStackEnd(stackEnd); 223 state->recordStackEnd(stackEnd);
185 state->copyStackUntilSafePointScope(); 224 state->copyStackUntilSafePointScope();
186 // m_unparkedThreadCount tracks amount of unparked threads. It is 225 // m_unparkedThreadCount tracks amount of unparked threads. It is
187 // positive if and only if we have requested other threads to park 226 // positive if and only if we have requested other threads to park
188 // at safe-points in preparation for GC. The last thread to park 227 // at safe-points in preparation for GC. The last thread to park
189 // itself will make the counter hit zero and should notify GC thread 228 // itself will make the counter hit zero and should notify GC thread
190 // that it is safe to proceed. 229 // that it is safe to proceed.
191 // If no other thread is waiting for other threads to park then 230 // If no other thread is waiting for other threads to park then
192 // this counter can be negative: if N threads are at safe-points 231 // this counter can be negative: if N threads are at safe-points
193 // the counter will be -N. 232 // the counter will be -N.
194 if (!atomicDecrement(&m_unparkedThreadCount)) { 233 if (!atomicDecrement(&m_unparkedThreadCount)) {
195 MutexLocker locker(m_mutex); 234 MutexLocker locker(m_mutex);
196 m_parked.signal(); // Safe point reached. 235 m_parked.signal(); // Safe point reached.
197 } 236 }
198 } 237 }
199 238
200 void enterSafePoint(ThreadState* state)
201 {
202 ASSERT(!state->isSweepInProgress());
203 pushAllRegisters(this, state, enterSafePointAfterPushRegisters);
204 }
205
206 void leaveSafePoint(ThreadState* state)
207 {
208 if (atomicIncrement(&m_unparkedThreadCount) > 0)
209 checkAndPark(state);
210 }
211
212 private:
213 static void parkAfterPushRegisters(SafePointBarrier* barrier, ThreadState* s tate, intptr_t* stackEnd)
214 {
215 barrier->doPark(state, stackEnd);
216 }
217
218 static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, Thre adState* state, intptr_t* stackEnd) 239 static void enterSafePointAfterPushRegisters(SafePointBarrier* barrier, Thre adState* state, intptr_t* stackEnd)
219 { 240 {
220 barrier->doEnterSafePoint(state, stackEnd); 241 barrier->doEnterSafePoint(state, stackEnd);
221 } 242 }
222 243
223 volatile int m_canResume; 244 volatile int m_canResume;
224 volatile int m_unparkedThreadCount; 245 volatile int m_unparkedThreadCount;
225 Mutex m_mutex; 246 Mutex m_mutex;
226 ThreadCondition m_parked; 247 ThreadCondition m_parked;
227 ThreadCondition m_resume; 248 ThreadCondition m_resume;
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 if (isConsistentForGC()) { 715 if (isConsistentForGC()) {
695 HeapStats scannedStats; 716 HeapStats scannedStats;
696 scannedStats.clear(); 717 scannedStats.clear();
697 for (int i = 0; i < NumberOfHeaps; i++) 718 for (int i = 0; i < NumberOfHeaps; i++)
698 m_heaps[i]->getScannedStats(scannedStats); 719 m_heaps[i]->getScannedStats(scannedStats);
699 ASSERT(scannedStats == stats); 720 ASSERT(scannedStats == stats);
700 } 721 }
701 #endif 722 #endif
702 } 723 }
703 724
704 void ThreadState::stopThreads() 725 bool ThreadState::stopThreads()
705 { 726 {
706 s_safePointBarrier->parkOthers(); 727 return s_safePointBarrier->parkOthers();
707 } 728 }
708 729
709 void ThreadState::resumeThreads() 730 void ThreadState::resumeThreads()
710 { 731 {
711 s_safePointBarrier->resumeOthers(); 732 s_safePointBarrier->resumeOthers();
712 } 733 }
713 734
714 void ThreadState::safePoint(StackState stackState) 735 void ThreadState::safePoint(StackState stackState)
715 { 736 {
716 checkThread(); 737 checkThread();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 state->safePoint(HeapPointersOnStack); 862 state->safePoint(HeapPointersOnStack);
842 } 863 }
843 864
844 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() 865 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads()
845 { 866 {
846 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); 867 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ());
847 return threads; 868 return threads;
848 } 869 }
849 870
850 } 871 }
OLDNEW
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698