OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_SAFEPOINT_H_ | 5 #ifndef RUNTIME_VM_SAFEPOINT_H_ |
6 #define RUNTIME_VM_SAFEPOINT_H_ | 6 #define RUNTIME_VM_SAFEPOINT_H_ |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
10 #include "vm/thread.h" | 10 #include "vm/thread.h" |
11 | 11 |
12 namespace dart { | 12 namespace dart { |
13 | 13 |
14 // A stack based scope that can be used to perform an operation after getting | 14 // A stack based scope that can be used to perform an operation after getting |
15 // all threads to a safepoint. At the end of the operation all the threads are | 15 // all threads to a safepoint. At the end of the operation all the threads are |
16 // resumed. | 16 // resumed. |
17 class SafepointOperationScope : public StackResource { | 17 class SafepointOperationScope : public StackResource { |
18 public: | 18 public: |
19 explicit SafepointOperationScope(Thread* T); | 19 explicit SafepointOperationScope(Thread* T); |
20 ~SafepointOperationScope(); | 20 ~SafepointOperationScope(); |
21 | 21 |
22 private: | 22 private: |
23 DISALLOW_COPY_AND_ASSIGN(SafepointOperationScope); | 23 DISALLOW_COPY_AND_ASSIGN(SafepointOperationScope); |
24 }; | 24 }; |
25 | 25 |
26 | |
27 // Implements handling of safepoint operations for all threads in an Isolate. | 26 // Implements handling of safepoint operations for all threads in an Isolate. |
28 class SafepointHandler { | 27 class SafepointHandler { |
29 public: | 28 public: |
30 explicit SafepointHandler(Isolate* I); | 29 explicit SafepointHandler(Isolate* I); |
31 ~SafepointHandler(); | 30 ~SafepointHandler(); |
32 | 31 |
33 void EnterSafepointUsingLock(Thread* T); | 32 void EnterSafepointUsingLock(Thread* T); |
34 void ExitSafepointUsingLock(Thread* T); | 33 void ExitSafepointUsingLock(Thread* T); |
35 | 34 |
36 void BlockForSafepoint(Thread* T); | 35 void BlockForSafepoint(Thread* T); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 int32_t safepoint_operation_count_; | 86 int32_t safepoint_operation_count_; |
88 | 87 |
89 // If a safepoint operation is currently in progress, this field contains | 88 // If a safepoint operation is currently in progress, this field contains |
90 // the thread that initiated the safepoint operation, otherwise it is NULL. | 89 // the thread that initiated the safepoint operation, otherwise it is NULL. |
91 Thread* owner_; | 90 Thread* owner_; |
92 | 91 |
93 friend class Isolate; | 92 friend class Isolate; |
94 friend class SafepointOperationScope; | 93 friend class SafepointOperationScope; |
95 }; | 94 }; |
96 | 95 |
97 | |
98 /* | 96 /* |
99 * Set of StackResource classes to track thread execution state transitions: | 97 * Set of StackResource classes to track thread execution state transitions: |
100 * | 98 * |
101 * kThreadInGenerated transitioning to | 99 * kThreadInGenerated transitioning to |
102 * ==> kThreadInVM: | 100 * ==> kThreadInVM: |
103 * - set_execution_state(kThreadInVM). | 101 * - set_execution_state(kThreadInVM). |
104 * - block if safepoint is requested. | 102 * - block if safepoint is requested. |
105 * ==> kThreadInNative: | 103 * ==> kThreadInNative: |
106 * - set_execution_state(kThreadInNative). | 104 * - set_execution_state(kThreadInNative). |
107 * - EnterSafepoint(). | 105 * - EnterSafepoint(). |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 SafepointHandler* handler() const { | 143 SafepointHandler* handler() const { |
146 ASSERT(thread()->isolate() != NULL); | 144 ASSERT(thread()->isolate() != NULL); |
147 ASSERT(thread()->isolate()->safepoint_handler() != NULL); | 145 ASSERT(thread()->isolate()->safepoint_handler() != NULL); |
148 return thread()->isolate()->safepoint_handler(); | 146 return thread()->isolate()->safepoint_handler(); |
149 } | 147 } |
150 | 148 |
151 private: | 149 private: |
152 DISALLOW_COPY_AND_ASSIGN(TransitionSafepointState); | 150 DISALLOW_COPY_AND_ASSIGN(TransitionSafepointState); |
153 }; | 151 }; |
154 | 152 |
155 | |
156 // TransitionGeneratedToVM is used to transition the safepoint state of a | 153 // TransitionGeneratedToVM is used to transition the safepoint state of a |
157 // thread from "running generated code" to "running vm code" and ensures | 154 // thread from "running generated code" to "running vm code" and ensures |
158 // that the state is reverted back to "running generated code" when | 155 // that the state is reverted back to "running generated code" when |
159 // exiting the scope/frame. | 156 // exiting the scope/frame. |
160 class TransitionGeneratedToVM : public TransitionSafepointState { | 157 class TransitionGeneratedToVM : public TransitionSafepointState { |
161 public: | 158 public: |
162 explicit TransitionGeneratedToVM(Thread* T) : TransitionSafepointState(T) { | 159 explicit TransitionGeneratedToVM(Thread* T) : TransitionSafepointState(T) { |
163 ASSERT(T == Thread::Current()); | 160 ASSERT(T == Thread::Current()); |
164 ASSERT(T->execution_state() == Thread::kThreadInGenerated); | 161 ASSERT(T->execution_state() == Thread::kThreadInGenerated); |
165 T->set_execution_state(Thread::kThreadInVM); | 162 T->set_execution_state(Thread::kThreadInVM); |
166 // Fast check to see if a safepoint is requested or not. | 163 // Fast check to see if a safepoint is requested or not. |
167 // We do the more expensive operation of blocking the thread | 164 // We do the more expensive operation of blocking the thread |
168 // only if a safepoint is requested. | 165 // only if a safepoint is requested. |
169 if (T->IsSafepointRequested()) { | 166 if (T->IsSafepointRequested()) { |
170 handler()->BlockForSafepoint(T); | 167 handler()->BlockForSafepoint(T); |
171 } | 168 } |
172 } | 169 } |
173 | 170 |
174 ~TransitionGeneratedToVM() { | 171 ~TransitionGeneratedToVM() { |
175 ASSERT(thread()->execution_state() == Thread::kThreadInVM); | 172 ASSERT(thread()->execution_state() == Thread::kThreadInVM); |
176 thread()->set_execution_state(Thread::kThreadInGenerated); | 173 thread()->set_execution_state(Thread::kThreadInGenerated); |
177 } | 174 } |
178 | 175 |
179 private: | 176 private: |
180 DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToVM); | 177 DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToVM); |
181 }; | 178 }; |
182 | 179 |
183 | |
184 // TransitionGeneratedToNative is used to transition the safepoint state of a | 180 // TransitionGeneratedToNative is used to transition the safepoint state of a |
185 // thread from "running generated code" to "running native code" and ensures | 181 // thread from "running generated code" to "running native code" and ensures |
186 // that the state is reverted back to "running generated code" when | 182 // that the state is reverted back to "running generated code" when |
187 // exiting the scope/frame. | 183 // exiting the scope/frame. |
188 class TransitionGeneratedToNative : public TransitionSafepointState { | 184 class TransitionGeneratedToNative : public TransitionSafepointState { |
189 public: | 185 public: |
190 explicit TransitionGeneratedToNative(Thread* T) | 186 explicit TransitionGeneratedToNative(Thread* T) |
191 : TransitionSafepointState(T) { | 187 : TransitionSafepointState(T) { |
192 // Native code is considered to be at a safepoint and so we mark it | 188 // Native code is considered to be at a safepoint and so we mark it |
193 // accordingly. | 189 // accordingly. |
194 ASSERT(T->execution_state() == Thread::kThreadInGenerated); | 190 ASSERT(T->execution_state() == Thread::kThreadInGenerated); |
195 T->set_execution_state(Thread::kThreadInNative); | 191 T->set_execution_state(Thread::kThreadInNative); |
196 T->EnterSafepoint(); | 192 T->EnterSafepoint(); |
197 } | 193 } |
198 | 194 |
199 ~TransitionGeneratedToNative() { | 195 ~TransitionGeneratedToNative() { |
200 // We are returning to generated code and so we are not at a safepoint | 196 // We are returning to generated code and so we are not at a safepoint |
201 // anymore. | 197 // anymore. |
202 ASSERT(thread()->execution_state() == Thread::kThreadInNative); | 198 ASSERT(thread()->execution_state() == Thread::kThreadInNative); |
203 thread()->ExitSafepoint(); | 199 thread()->ExitSafepoint(); |
204 thread()->set_execution_state(Thread::kThreadInGenerated); | 200 thread()->set_execution_state(Thread::kThreadInGenerated); |
205 } | 201 } |
206 | 202 |
207 private: | 203 private: |
208 DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToNative); | 204 DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToNative); |
209 }; | 205 }; |
210 | 206 |
211 | |
212 // TransitionVMToBlocked is used to transition the safepoint state of a | 207 // TransitionVMToBlocked is used to transition the safepoint state of a |
213 // thread from "running vm code" to "blocked on a monitor" and ensures | 208 // thread from "running vm code" to "blocked on a monitor" and ensures |
214 // that the state is reverted back to "running vm code" when | 209 // that the state is reverted back to "running vm code" when |
215 // exiting the scope/frame. | 210 // exiting the scope/frame. |
216 class TransitionVMToBlocked : public TransitionSafepointState { | 211 class TransitionVMToBlocked : public TransitionSafepointState { |
217 public: | 212 public: |
218 explicit TransitionVMToBlocked(Thread* T) : TransitionSafepointState(T) { | 213 explicit TransitionVMToBlocked(Thread* T) : TransitionSafepointState(T) { |
219 // A thread blocked on a monitor is considered to be at a safepoint. | 214 // A thread blocked on a monitor is considered to be at a safepoint. |
220 ASSERT(T->execution_state() == Thread::kThreadInVM); | 215 ASSERT(T->execution_state() == Thread::kThreadInVM); |
221 T->set_execution_state(Thread::kThreadInBlockedState); | 216 T->set_execution_state(Thread::kThreadInBlockedState); |
222 T->EnterSafepoint(); | 217 T->EnterSafepoint(); |
223 } | 218 } |
224 | 219 |
225 ~TransitionVMToBlocked() { | 220 ~TransitionVMToBlocked() { |
226 // We are returning to vm code and so we are not at a safepoint anymore. | 221 // We are returning to vm code and so we are not at a safepoint anymore. |
227 ASSERT(thread()->execution_state() == Thread::kThreadInBlockedState); | 222 ASSERT(thread()->execution_state() == Thread::kThreadInBlockedState); |
228 thread()->ExitSafepoint(); | 223 thread()->ExitSafepoint(); |
229 thread()->set_execution_state(Thread::kThreadInVM); | 224 thread()->set_execution_state(Thread::kThreadInVM); |
230 } | 225 } |
231 | 226 |
232 private: | 227 private: |
233 DISALLOW_COPY_AND_ASSIGN(TransitionVMToBlocked); | 228 DISALLOW_COPY_AND_ASSIGN(TransitionVMToBlocked); |
234 }; | 229 }; |
235 | 230 |
236 | |
237 // TransitionVMToNative is used to transition the safepoint state of a | 231 // TransitionVMToNative is used to transition the safepoint state of a |
238 // thread from "running vm code" to "running native code" and ensures | 232 // thread from "running vm code" to "running native code" and ensures |
239 // that the state is reverted back to "running vm code" when | 233 // that the state is reverted back to "running vm code" when |
240 // exiting the scope/frame. | 234 // exiting the scope/frame. |
241 class TransitionVMToNative : public TransitionSafepointState { | 235 class TransitionVMToNative : public TransitionSafepointState { |
242 public: | 236 public: |
243 explicit TransitionVMToNative(Thread* T) : TransitionSafepointState(T) { | 237 explicit TransitionVMToNative(Thread* T) : TransitionSafepointState(T) { |
244 // A thread running native code is considered to be at a safepoint. | 238 // A thread running native code is considered to be at a safepoint. |
245 ASSERT(T->execution_state() == Thread::kThreadInVM); | 239 ASSERT(T->execution_state() == Thread::kThreadInVM); |
246 T->set_execution_state(Thread::kThreadInNative); | 240 T->set_execution_state(Thread::kThreadInNative); |
247 T->EnterSafepoint(); | 241 T->EnterSafepoint(); |
248 } | 242 } |
249 | 243 |
250 ~TransitionVMToNative() { | 244 ~TransitionVMToNative() { |
251 // We are returning to vm code and so we are not at a safepoint anymore. | 245 // We are returning to vm code and so we are not at a safepoint anymore. |
252 ASSERT(thread()->execution_state() == Thread::kThreadInNative); | 246 ASSERT(thread()->execution_state() == Thread::kThreadInNative); |
253 thread()->ExitSafepoint(); | 247 thread()->ExitSafepoint(); |
254 thread()->set_execution_state(Thread::kThreadInVM); | 248 thread()->set_execution_state(Thread::kThreadInVM); |
255 } | 249 } |
256 | 250 |
257 private: | 251 private: |
258 DISALLOW_COPY_AND_ASSIGN(TransitionVMToNative); | 252 DISALLOW_COPY_AND_ASSIGN(TransitionVMToNative); |
259 }; | 253 }; |
260 | 254 |
261 | |
262 // TransitionVMToGenerated is used to transition the safepoint state of a | 255 // TransitionVMToGenerated is used to transition the safepoint state of a |
263 // thread from "running vm code" to "running generated code" and ensures | 256 // thread from "running vm code" to "running generated code" and ensures |
264 // that the state is reverted back to "running vm code" when | 257 // that the state is reverted back to "running vm code" when |
265 // exiting the scope/frame. | 258 // exiting the scope/frame. |
266 class TransitionVMToGenerated : public TransitionSafepointState { | 259 class TransitionVMToGenerated : public TransitionSafepointState { |
267 public: | 260 public: |
268 explicit TransitionVMToGenerated(Thread* T) : TransitionSafepointState(T) { | 261 explicit TransitionVMToGenerated(Thread* T) : TransitionSafepointState(T) { |
269 ASSERT(T == Thread::Current()); | 262 ASSERT(T == Thread::Current()); |
270 ASSERT(T->execution_state() == Thread::kThreadInVM); | 263 ASSERT(T->execution_state() == Thread::kThreadInVM); |
271 T->set_execution_state(Thread::kThreadInGenerated); | 264 T->set_execution_state(Thread::kThreadInGenerated); |
272 } | 265 } |
273 | 266 |
274 ~TransitionVMToGenerated() { | 267 ~TransitionVMToGenerated() { |
275 ASSERT(thread()->execution_state() == Thread::kThreadInGenerated); | 268 ASSERT(thread()->execution_state() == Thread::kThreadInGenerated); |
276 thread()->set_execution_state(Thread::kThreadInVM); | 269 thread()->set_execution_state(Thread::kThreadInVM); |
277 // Fast check to see if a safepoint is requested or not. | 270 // Fast check to see if a safepoint is requested or not. |
278 // We do the more expensive operation of blocking the thread | 271 // We do the more expensive operation of blocking the thread |
279 // only if a safepoint is requested. | 272 // only if a safepoint is requested. |
280 if (thread()->IsSafepointRequested()) { | 273 if (thread()->IsSafepointRequested()) { |
281 handler()->BlockForSafepoint(thread()); | 274 handler()->BlockForSafepoint(thread()); |
282 } | 275 } |
283 } | 276 } |
284 | 277 |
285 private: | 278 private: |
286 DISALLOW_COPY_AND_ASSIGN(TransitionVMToGenerated); | 279 DISALLOW_COPY_AND_ASSIGN(TransitionVMToGenerated); |
287 }; | 280 }; |
288 | 281 |
289 | |
290 // TransitionNativeToVM is used to transition the safepoint state of a | 282 // TransitionNativeToVM is used to transition the safepoint state of a |
291 // thread from "running native code" to "running vm code" and ensures | 283 // thread from "running native code" to "running vm code" and ensures |
292 // that the state is reverted back to "running native code" when | 284 // that the state is reverted back to "running native code" when |
293 // exiting the scope/frame. | 285 // exiting the scope/frame. |
294 class TransitionNativeToVM : public TransitionSafepointState { | 286 class TransitionNativeToVM : public TransitionSafepointState { |
295 public: | 287 public: |
296 explicit TransitionNativeToVM(Thread* T) : TransitionSafepointState(T) { | 288 explicit TransitionNativeToVM(Thread* T) : TransitionSafepointState(T) { |
297 // We are about to execute vm code and so we are not at a safepoint anymore. | 289 // We are about to execute vm code and so we are not at a safepoint anymore. |
298 ASSERT(T->execution_state() == Thread::kThreadInNative); | 290 ASSERT(T->execution_state() == Thread::kThreadInNative); |
299 T->ExitSafepoint(); | 291 T->ExitSafepoint(); |
300 T->set_execution_state(Thread::kThreadInVM); | 292 T->set_execution_state(Thread::kThreadInVM); |
301 } | 293 } |
302 | 294 |
303 ~TransitionNativeToVM() { | 295 ~TransitionNativeToVM() { |
304 // We are returning to native code and so we are at a safepoint. | 296 // We are returning to native code and so we are at a safepoint. |
305 ASSERT(thread()->execution_state() == Thread::kThreadInVM); | 297 ASSERT(thread()->execution_state() == Thread::kThreadInVM); |
306 thread()->set_execution_state(Thread::kThreadInNative); | 298 thread()->set_execution_state(Thread::kThreadInNative); |
307 thread()->EnterSafepoint(); | 299 thread()->EnterSafepoint(); |
308 } | 300 } |
309 | 301 |
310 private: | 302 private: |
311 DISALLOW_COPY_AND_ASSIGN(TransitionNativeToVM); | 303 DISALLOW_COPY_AND_ASSIGN(TransitionNativeToVM); |
312 }; | 304 }; |
313 | 305 |
314 | |
315 // TransitionToGenerated is used to transition the safepoint state of a | 306 // TransitionToGenerated is used to transition the safepoint state of a |
316 // thread from "running vm code" or "running native code" to | 307 // thread from "running vm code" or "running native code" to |
317 // "running generated code" and ensures that the state is reverted back | 308 // "running generated code" and ensures that the state is reverted back |
318 // to "running vm code" or "running native code" when exiting the | 309 // to "running vm code" or "running native code" when exiting the |
319 // scope/frame. | 310 // scope/frame. |
320 class TransitionToGenerated : public TransitionSafepointState { | 311 class TransitionToGenerated : public TransitionSafepointState { |
321 public: | 312 public: |
322 explicit TransitionToGenerated(Thread* T) | 313 explicit TransitionToGenerated(Thread* T) |
323 : TransitionSafepointState(T), execution_state_(T->execution_state()) { | 314 : TransitionSafepointState(T), execution_state_(T->execution_state()) { |
324 ASSERT(T == Thread::Current()); | 315 ASSERT(T == Thread::Current()); |
(...skipping 14 matching lines...) Expand all Loading... |
339 ASSERT(execution_state_ == Thread::kThreadInVM); | 330 ASSERT(execution_state_ == Thread::kThreadInVM); |
340 thread()->set_execution_state(Thread::kThreadInVM); | 331 thread()->set_execution_state(Thread::kThreadInVM); |
341 } | 332 } |
342 } | 333 } |
343 | 334 |
344 private: | 335 private: |
345 uint32_t execution_state_; | 336 uint32_t execution_state_; |
346 DISALLOW_COPY_AND_ASSIGN(TransitionToGenerated); | 337 DISALLOW_COPY_AND_ASSIGN(TransitionToGenerated); |
347 }; | 338 }; |
348 | 339 |
349 | |
350 // TransitionToVM is used to transition the safepoint state of a | 340 // TransitionToVM is used to transition the safepoint state of a |
351 // thread from "running native code" to "running vm code" | 341 // thread from "running native code" to "running vm code" |
352 // and ensures that the state is reverted back to "running native code" | 342 // and ensures that the state is reverted back to "running native code" |
353 // when exiting the scope/frame. | 343 // when exiting the scope/frame. |
354 // This transition helper is mainly used in the error path of the | 344 // This transition helper is mainly used in the error path of the |
355 // Dart API implementations where we sometimes do not have an explicit | 345 // Dart API implementations where we sometimes do not have an explicit |
356 // transition set up. | 346 // transition set up. |
357 class TransitionToVM : public TransitionSafepointState { | 347 class TransitionToVM : public TransitionSafepointState { |
358 public: | 348 public: |
359 explicit TransitionToVM(Thread* T) | 349 explicit TransitionToVM(Thread* T) |
(...skipping 17 matching lines...) Expand all Loading... |
377 } | 367 } |
378 | 368 |
379 private: | 369 private: |
380 uint32_t execution_state_; | 370 uint32_t execution_state_; |
381 DISALLOW_COPY_AND_ASSIGN(TransitionToVM); | 371 DISALLOW_COPY_AND_ASSIGN(TransitionToVM); |
382 }; | 372 }; |
383 | 373 |
384 } // namespace dart | 374 } // namespace dart |
385 | 375 |
386 #endif // RUNTIME_VM_SAFEPOINT_H_ | 376 #endif // RUNTIME_VM_SAFEPOINT_H_ |
OLD | NEW |