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

Side by Side Diff: runtime/vm/message_handler.cc

Issue 1665773004: Add necessary support functions so that embedders can implemented pause on start and exit (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 #include "vm/message_handler.h" 5 #include "vm/message_handler.h"
6 6
7 #include "vm/dart.h" 7 #include "vm/dart.h"
8 #include "vm/lockers.h" 8 #include "vm/lockers.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/object_store.h" 10 #include "vm/object_store.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } 54 }
55 } 55 }
56 56
57 57
58 MessageHandler::MessageHandler() 58 MessageHandler::MessageHandler()
59 : queue_(new MessageQueue()), 59 : queue_(new MessageQueue()),
60 oob_queue_(new MessageQueue()), 60 oob_queue_(new MessageQueue()),
61 oob_message_handling_allowed_(true), 61 oob_message_handling_allowed_(true),
62 live_ports_(0), 62 live_ports_(0),
63 paused_(0), 63 paused_(0),
64 pause_on_start_(false), 64 should_pause_on_start_(false),
65 pause_on_exit_(false), 65 should_pause_on_exit_(false),
66 paused_on_start_(false), 66 is_paused_on_start_(false),
67 paused_on_exit_(false), 67 is_paused_on_exit_(false),
68 paused_timestamp_(-1), 68 paused_timestamp_(-1),
69 pool_(NULL), 69 pool_(NULL),
70 task_(NULL), 70 task_(NULL),
71 start_callback_(NULL), 71 start_callback_(NULL),
72 end_callback_(NULL), 72 end_callback_(NULL),
73 callback_data_(0) { 73 callback_data_(0) {
74 ASSERT(queue_ != NULL); 74 ASSERT(queue_ != NULL);
75 ASSERT(oob_queue_ != NULL); 75 ASSERT(oob_queue_ != NULL);
76 } 76 }
77 77
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 // assigned to a thread pool. 251 // assigned to a thread pool.
252 MonitorLocker ml(&monitor_); 252 MonitorLocker ml(&monitor_);
253 ASSERT(pool_ == NULL); 253 ASSERT(pool_ == NULL);
254 #if defined(DEBUG) 254 #if defined(DEBUG)
255 CheckAccess(); 255 CheckAccess();
256 #endif 256 #endif
257 return HandleMessages(true, false); 257 return HandleMessages(true, false);
258 } 258 }
259 259
260 260
261 MessageHandler::MessageStatus MessageHandler::HandleAllMessages() {
262 // We can only call HandleAllMessages when this handler is not
263 // assigned to a thread pool.
264 MonitorLocker ml(&monitor_);
265 ASSERT(pool_ == NULL);
266 #if defined(DEBUG)
267 CheckAccess();
268 #endif
269 return HandleMessages(true, true);
270 }
271
272
261 MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() { 273 MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() {
262 if (!oob_message_handling_allowed_) { 274 if (!oob_message_handling_allowed_) {
263 return kOK; 275 return kOK;
264 } 276 }
265 MonitorLocker ml(&monitor_); 277 MonitorLocker ml(&monitor_);
266 #if defined(DEBUG) 278 #if defined(DEBUG)
267 CheckAccess(); 279 CheckAccess();
268 #endif 280 #endif
269 return HandleMessages(false, false); 281 return HandleMessages(false, false);
270 } 282 }
271 283
272 284
285 bool MessageHandler::ShouldPauseOnStart() const {
286 Isolate* owning_isolate = isolate();
287 if (owning_isolate == NULL) {
288 return false;
289 }
290 return should_pause_on_start() && owning_isolate->is_runnable();
291 }
292
293
294 bool MessageHandler::ShouldPauseOnExit() const {
295 Isolate* owning_isolate = isolate();
296 if (owning_isolate == NULL) {
297 return false;
298 }
299 return should_pause_on_exit() && owning_isolate->is_runnable();
300 }
301
302
273 bool MessageHandler::HasOOBMessages() { 303 bool MessageHandler::HasOOBMessages() {
274 MonitorLocker ml(&monitor_); 304 MonitorLocker ml(&monitor_);
275 return !oob_queue_->IsEmpty(); 305 return !oob_queue_->IsEmpty();
276 } 306 }
277 307
278 308
279 static bool ShouldPause(MessageHandler::MessageStatus status) { 309 static bool ShouldPause(MessageHandler::MessageStatus status) {
280 // If we are restarting or shutting down, we do not want to honor 310 // If we are restarting or shutting down, we do not want to honor
281 // pause_on_start or pause_on_exit. 311 // should_pause_on_start or should_pause_on_exit.
282 return (status != MessageHandler::kRestart && 312 return (status != MessageHandler::kRestart &&
283 status != MessageHandler::kShutdown); 313 status != MessageHandler::kShutdown);
turnidge 2016/02/03 23:17:56 I wonder if we can fold ShouldPause() into ShoudlP
Cutch 2016/02/03 23:25:07 Done.
284 } 314 }
285 315
286 316
287 void MessageHandler::TaskCallback() { 317 void MessageHandler::TaskCallback() {
288 ASSERT(Isolate::Current() == NULL); 318 ASSERT(Isolate::Current() == NULL);
289 MessageStatus status = kOK; 319 MessageStatus status = kOK;
290 bool run_end_callback = false; 320 bool run_end_callback = false;
291 { 321 {
292 // We will occasionally release and reacquire this monitor in this 322 // We will occasionally release and reacquire this monitor in this
293 // function. Whenever we reacquire the monitor we *must* process 323 // function. Whenever we reacquire the monitor we *must* process
294 // all pending OOB messages, or we may miss a request for vm 324 // all pending OOB messages, or we may miss a request for vm
295 // shutdown. 325 // shutdown.
296 MonitorLocker ml(&monitor_); 326 MonitorLocker ml(&monitor_);
297 if (pause_on_start()) { 327 if (ShouldPauseOnStart()) {
298 if (!paused_on_start_) { 328 if (!is_paused_on_start_) {
299 // Temporarily release the monitor when calling out to 329 PausedOnStartLocked(true);
300 // NotifyPauseOnStart. This avoids a dead lock that can occur
301 // when this message handler tries to post a message while a
302 // message is being posted to it.
303 paused_on_start_ = true;
304 paused_timestamp_ = OS::GetCurrentTimeMillis();
305 monitor_.Exit();
306 NotifyPauseOnStart();
307 monitor_.Enter();
308 } 330 }
309 // More messages may have come in before we (re)acquired the monitor. 331 // More messages may have come in before we (re)acquired the monitor.
310 status = HandleMessages(false, false); 332 status = HandleMessages(false, false);
311 if (ShouldPause(status) && pause_on_start()) { 333 if (ShouldPause(status) && ShouldPauseOnStart()) {
312 // Still paused. 334 // Still paused.
313 ASSERT(oob_queue_->IsEmpty()); 335 ASSERT(oob_queue_->IsEmpty());
314 task_ = NULL; // No task in queue. 336 task_ = NULL; // No task in queue.
315 return; 337 return;
316 } else { 338 } else {
317 paused_on_start_ = false; 339 PausedOnStartLocked(false);
318 paused_timestamp_ = -1;
319 } 340 }
320 } 341 }
321 342
322 if (status == kOK) { 343 if (status == kOK) {
323 if (start_callback_) { 344 if (start_callback_) {
324 // Initialize the message handler by running its start function, 345 // Initialize the message handler by running its start function,
325 // if we have one. For an isolate, this will run the isolate's 346 // if we have one. For an isolate, this will run the isolate's
326 // main() function. 347 // main() function.
327 // 348 //
328 // Release the monitor_ temporarily while we call the start callback. 349 // Release the monitor_ temporarily while we call the start callback.
329 monitor_.Exit(); 350 monitor_.Exit();
330 status = start_callback_(callback_data_); 351 status = start_callback_(callback_data_);
331 ASSERT(Isolate::Current() == NULL); 352 ASSERT(Isolate::Current() == NULL);
332 start_callback_ = NULL; 353 start_callback_ = NULL;
333 monitor_.Enter(); 354 monitor_.Enter();
334 } 355 }
335 356
336 // Handle any pending messages for this message handler. 357 // Handle any pending messages for this message handler.
337 if (status != kShutdown) { 358 if (status != kShutdown) {
338 status = HandleMessages((status == kOK), true); 359 status = HandleMessages((status == kOK), true);
339 } 360 }
340 } 361 }
341 362
342 // The isolate exits when it encounters an error or when it no 363 // The isolate exits when it encounters an error or when it no
343 // longer has live ports. 364 // longer has live ports.
344 if (status != kOK || !HasLivePorts()) { 365 if (status != kOK || !HasLivePorts()) {
345 if (ShouldPause(status) && pause_on_exit()) { 366 if (ShouldPause(status) && ShouldPauseOnExit()) {
346 if (!paused_on_exit_) { 367 if (!is_paused_on_exit_) {
347 if (FLAG_trace_service_pause_events) { 368 if (FLAG_trace_service_pause_events) {
348 OS::PrintErr("Isolate %s paused before exiting. " 369 OS::PrintErr("Isolate %s paused before exiting. "
349 "Use the Observatory to release it.\n", name()); 370 "Use the Observatory to release it.\n", name());
350 } 371 }
351 // Temporarily release the monitor when calling out to 372 PausedOnExitLocked(true);
352 // NotifyPauseOnExit. This avoids a dead lock that can
353 // occur when this message handler tries to post a message
354 // while a message is being posted to it.
355 paused_on_exit_ = true;
356 paused_timestamp_ = OS::GetCurrentTimeMillis();
357 monitor_.Exit();
358 NotifyPauseOnExit();
359 monitor_.Enter();
360
361 // More messages may have come in while we released the monitor. 373 // More messages may have come in while we released the monitor.
362 HandleMessages(false, false); 374 HandleMessages(false, false);
363 } 375 }
364 if (ShouldPause(status) && pause_on_exit()) { 376 if (ShouldPause(status) && ShouldPauseOnExit()) {
365 // Still paused. 377 // Still paused.
366 ASSERT(oob_queue_->IsEmpty()); 378 ASSERT(oob_queue_->IsEmpty());
367 task_ = NULL; // No task in queue. 379 task_ = NULL; // No task in queue.
368 return; 380 return;
369 } else { 381 } else {
370 paused_on_exit_ = false; 382 PausedOnExitLocked(false);
371 paused_timestamp_ = -1;
372 } 383 }
373 } 384 }
374 if (FLAG_trace_isolates) { 385 if (FLAG_trace_isolates) {
375 if (status != kOK && isolate() != NULL) { 386 if (status != kOK && isolate() != NULL) {
376 const Error& error = 387 const Error& error =
377 Error::Handle(isolate()->object_store()->sticky_error()); 388 Error::Handle(isolate()->object_store()->sticky_error());
378 OS::Print("[-] Stopping message handler (%s):\n" 389 OS::Print("[-] Stopping message handler (%s):\n"
379 "\thandler: %s\n" 390 "\thandler: %s\n"
380 "\terror: %s\n", 391 "\terror: %s\n",
381 MessageStatusString(status), name(), error.ToCString()); 392 MessageStatusString(status), name(), error.ToCString());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 447
437 void MessageHandler::decrement_live_ports() { 448 void MessageHandler::decrement_live_ports() {
438 MonitorLocker ml(&monitor_); 449 MonitorLocker ml(&monitor_);
439 #if defined(DEBUG) 450 #if defined(DEBUG)
440 CheckAccess(); 451 CheckAccess();
441 #endif 452 #endif
442 live_ports_--; 453 live_ports_--;
443 } 454 }
444 455
445 456
457 void MessageHandler::PausedOnStart(bool paused) {
458 MonitorLocker ml(&monitor_);
459 PausedOnStartLocked(paused);
460 }
461
462
463 void MessageHandler::PausedOnStartLocked(bool paused) {
464 if (paused) {
turnidge 2016/02/03 23:17:57 Do we want to ASSERT(!is_paused_on_start_)? Simil
Cutch 2016/02/03 23:25:07 Done.
465 is_paused_on_start_ = true;
466 paused_timestamp_ = OS::GetCurrentTimeMillis();
467 } else {
468 is_paused_on_start_ = false;
469 paused_timestamp_ = -1;
470 }
471 if (is_paused_on_start_) {
472 // Temporarily release the monitor when calling out to
473 // NotifyPauseOnStart. This avoids a dead lock that can occur
474 // when this message handler tries to post a message while a
475 // message is being posted to it.
476 monitor_.Exit();
477 NotifyPauseOnStart();
478 monitor_.Enter();
479 } else {
480 // Resumed. Clear the resume request of the owning isolate.
481 Isolate* owning_isolate = isolate();
482 if (owning_isolate != NULL) {
483 owning_isolate->GetAndClearResumeRequest();
484 }
485 }
486 }
487
488
489 void MessageHandler::PausedOnExit(bool paused) {
490 MonitorLocker ml(&monitor_);
491 PausedOnExitLocked(paused);
492 }
493
494
495 void MessageHandler::PausedOnExitLocked(bool paused) {
496 if (paused) {
497 is_paused_on_exit_ = true;
498 paused_timestamp_ = OS::GetCurrentTimeMillis();
499 } else {
500 is_paused_on_exit_ = false;
501 paused_timestamp_ = -1;
502 }
503 if (is_paused_on_exit_) {
504 // Temporarily release the monitor when calling out to
505 // NotifyPauseOnExit. This avoids a dead lock that can
506 // occur when this message handler tries to post a message
507 // while a message is being posted to it.
508 monitor_.Exit();
509 NotifyPauseOnExit();
510 monitor_.Enter();
511 } else {
512 // Resumed. Clear the resume request of the owning isolate.
513 Isolate* owning_isolate = isolate();
514 if (owning_isolate != NULL) {
515 owning_isolate->GetAndClearResumeRequest();
516 }
517 }
518 }
519
520
446 MessageHandler::AcquiredQueues::AcquiredQueues() 521 MessageHandler::AcquiredQueues::AcquiredQueues()
447 : handler_(NULL) { 522 : handler_(NULL) {
448 } 523 }
449 524
450 525
451 MessageHandler::AcquiredQueues::~AcquiredQueues() { 526 MessageHandler::AcquiredQueues::~AcquiredQueues() {
452 Reset(NULL); 527 Reset(NULL);
453 } 528 }
454 529
455 530
(...skipping 15 matching lines...) Expand all
471 546
472 547
473 void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) { 548 void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) {
474 ASSERT(acquired_queues != NULL); 549 ASSERT(acquired_queues != NULL);
475 // No double dipping. 550 // No double dipping.
476 ASSERT(acquired_queues->handler_ == NULL); 551 ASSERT(acquired_queues->handler_ == NULL);
477 acquired_queues->Reset(this); 552 acquired_queues->Reset(this);
478 } 553 }
479 554
480 } // namespace dart 555 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698