| OLD | NEW |
| 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 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 MessageStatus status = kOK; | 318 MessageStatus status = kOK; |
| 319 bool run_end_callback = false; | 319 bool run_end_callback = false; |
| 320 { | 320 { |
| 321 // We will occasionally release and reacquire this monitor in this | 321 // We will occasionally release and reacquire this monitor in this |
| 322 // function. Whenever we reacquire the monitor we *must* process | 322 // function. Whenever we reacquire the monitor we *must* process |
| 323 // all pending OOB messages, or we may miss a request for vm | 323 // all pending OOB messages, or we may miss a request for vm |
| 324 // shutdown. | 324 // shutdown. |
| 325 MonitorLocker ml(&monitor_); | 325 MonitorLocker ml(&monitor_); |
| 326 if (ShouldPauseOnStart(kOK)) { | 326 if (ShouldPauseOnStart(kOK)) { |
| 327 if (!is_paused_on_start()) { | 327 if (!is_paused_on_start()) { |
| 328 PausedOnStartLocked(true); | 328 PausedOnStartLocked(&ml, true); |
| 329 } | 329 } |
| 330 // More messages may have come in before we (re)acquired the monitor. | 330 // More messages may have come in before we (re)acquired the monitor. |
| 331 status = HandleMessages(&ml, false, false); | 331 status = HandleMessages(&ml, false, false); |
| 332 if (ShouldPauseOnStart(status)) { | 332 if (ShouldPauseOnStart(status)) { |
| 333 // Still paused. | 333 // Still paused. |
| 334 ASSERT(oob_queue_->IsEmpty()); | 334 ASSERT(oob_queue_->IsEmpty()); |
| 335 task_ = NULL; // No task in queue. | 335 task_ = NULL; // No task in queue. |
| 336 return; | 336 return; |
| 337 } else { | 337 } else { |
| 338 PausedOnStartLocked(false); | 338 PausedOnStartLocked(&ml, false); |
| 339 } | 339 } |
| 340 } | 340 } |
| 341 | 341 |
| 342 if (status == kOK) { | 342 if (status == kOK) { |
| 343 if (start_callback_) { | 343 if (start_callback_) { |
| 344 // Initialize the message handler by running its start function, | 344 // Initialize the message handler by running its start function, |
| 345 // if we have one. For an isolate, this will run the isolate's | 345 // if we have one. For an isolate, this will run the isolate's |
| 346 // main() function. | 346 // main() function. |
| 347 // | 347 // |
| 348 // Release the monitor_ temporarily while we call the start callback. | 348 // Release the monitor_ temporarily while we call the start callback. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 361 | 361 |
| 362 // The isolate exits when it encounters an error or when it no | 362 // The isolate exits when it encounters an error or when it no |
| 363 // longer has live ports. | 363 // longer has live ports. |
| 364 if (status != kOK || !HasLivePorts()) { | 364 if (status != kOK || !HasLivePorts()) { |
| 365 if (ShouldPauseOnExit(status)) { | 365 if (ShouldPauseOnExit(status)) { |
| 366 if (!is_paused_on_exit()) { | 366 if (!is_paused_on_exit()) { |
| 367 if (FLAG_trace_service_pause_events) { | 367 if (FLAG_trace_service_pause_events) { |
| 368 OS::PrintErr("Isolate %s paused before exiting. " | 368 OS::PrintErr("Isolate %s paused before exiting. " |
| 369 "Use the Observatory to release it.\n", name()); | 369 "Use the Observatory to release it.\n", name()); |
| 370 } | 370 } |
| 371 PausedOnExitLocked(true); | 371 PausedOnExitLocked(&ml, true); |
| 372 // More messages may have come in while we released the monitor. | 372 // More messages may have come in while we released the monitor. |
| 373 status = HandleMessages(&ml, false, false); | 373 status = HandleMessages(&ml, false, false); |
| 374 } | 374 } |
| 375 if (ShouldPauseOnExit(status)) { | 375 if (ShouldPauseOnExit(status)) { |
| 376 // Still paused. | 376 // Still paused. |
| 377 ASSERT(oob_queue_->IsEmpty()); | 377 ASSERT(oob_queue_->IsEmpty()); |
| 378 task_ = NULL; // No task in queue. | 378 task_ = NULL; // No task in queue. |
| 379 return; | 379 return; |
| 380 } else { | 380 } else { |
| 381 PausedOnExitLocked(false); | 381 PausedOnExitLocked(&ml, false); |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 if (FLAG_trace_isolates) { | 384 if (FLAG_trace_isolates) { |
| 385 if (status != kOK && isolate() != NULL) { | 385 if (status != kOK && isolate() != NULL) { |
| 386 const Error& error = Error::Handle(thread()->sticky_error()); | 386 const Error& error = Error::Handle(thread()->sticky_error()); |
| 387 OS::Print("[-] Stopping message handler (%s):\n" | 387 OS::Print("[-] Stopping message handler (%s):\n" |
| 388 "\thandler: %s\n" | 388 "\thandler: %s\n" |
| 389 "\terror: %s\n", | 389 "\terror: %s\n", |
| 390 MessageStatusString(status), name(), error.ToCString()); | 390 MessageStatusString(status), name(), error.ToCString()); |
| 391 } else { | 391 } else { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 MonitorLocker ml(&monitor_); | 447 MonitorLocker ml(&monitor_); |
| 448 #if defined(DEBUG) | 448 #if defined(DEBUG) |
| 449 CheckAccess(); | 449 CheckAccess(); |
| 450 #endif | 450 #endif |
| 451 live_ports_--; | 451 live_ports_--; |
| 452 } | 452 } |
| 453 | 453 |
| 454 | 454 |
| 455 void MessageHandler::PausedOnStart(bool paused) { | 455 void MessageHandler::PausedOnStart(bool paused) { |
| 456 MonitorLocker ml(&monitor_); | 456 MonitorLocker ml(&monitor_); |
| 457 PausedOnStartLocked(paused); | 457 PausedOnStartLocked(&ml, paused); |
| 458 } | 458 } |
| 459 | 459 |
| 460 | 460 |
| 461 void MessageHandler::PausedOnStartLocked(bool paused) { | 461 void MessageHandler::PausedOnStartLocked(MonitorLocker* ml, bool paused) { |
| 462 if (paused) { | 462 if (paused) { |
| 463 ASSERT(!is_paused_on_start_); | 463 ASSERT(!is_paused_on_start_); |
| 464 is_paused_on_start_ = true; | 464 is_paused_on_start_ = true; |
| 465 paused_timestamp_ = OS::GetCurrentTimeMillis(); | 465 paused_timestamp_ = OS::GetCurrentTimeMillis(); |
| 466 } else { | 466 } else { |
| 467 ASSERT(is_paused_on_start_); | 467 ASSERT(is_paused_on_start_); |
| 468 is_paused_on_start_ = false; | 468 is_paused_on_start_ = false; |
| 469 paused_timestamp_ = -1; | 469 paused_timestamp_ = -1; |
| 470 } | 470 } |
| 471 if (is_paused_on_start_) { | 471 if (is_paused_on_start_) { |
| 472 // Temporarily release the monitor when calling out to | 472 // Temporarily release the monitor when calling out to |
| 473 // NotifyPauseOnStart. This avoids a dead lock that can occur | 473 // NotifyPauseOnStart. This avoids a dead lock that can occur |
| 474 // when this message handler tries to post a message while a | 474 // when this message handler tries to post a message while a |
| 475 // message is being posted to it. | 475 // message is being posted to it. |
| 476 monitor_.Exit(); | 476 ml->Exit(); |
| 477 NotifyPauseOnStart(); | 477 NotifyPauseOnStart(); |
| 478 monitor_.Enter(); | 478 ml->Enter(); |
| 479 } else { | 479 } else { |
| 480 // Resumed. Clear the resume request of the owning isolate. | 480 // Resumed. Clear the resume request of the owning isolate. |
| 481 Isolate* owning_isolate = isolate(); | 481 Isolate* owning_isolate = isolate(); |
| 482 if (owning_isolate != NULL) { | 482 if (owning_isolate != NULL) { |
| 483 owning_isolate->GetAndClearResumeRequest(); | 483 owning_isolate->GetAndClearResumeRequest(); |
| 484 } | 484 } |
| 485 } | 485 } |
| 486 } | 486 } |
| 487 | 487 |
| 488 | 488 |
| 489 void MessageHandler::PausedOnExit(bool paused) { | 489 void MessageHandler::PausedOnExit(bool paused) { |
| 490 MonitorLocker ml(&monitor_); | 490 MonitorLocker ml(&monitor_); |
| 491 PausedOnExitLocked(paused); | 491 PausedOnExitLocked(&ml, paused); |
| 492 } | 492 } |
| 493 | 493 |
| 494 | 494 |
| 495 void MessageHandler::PausedOnExitLocked(bool paused) { | 495 void MessageHandler::PausedOnExitLocked(MonitorLocker* ml, bool paused) { |
| 496 if (paused) { | 496 if (paused) { |
| 497 ASSERT(!is_paused_on_exit_); | 497 ASSERT(!is_paused_on_exit_); |
| 498 is_paused_on_exit_ = true; | 498 is_paused_on_exit_ = true; |
| 499 paused_timestamp_ = OS::GetCurrentTimeMillis(); | 499 paused_timestamp_ = OS::GetCurrentTimeMillis(); |
| 500 } else { | 500 } else { |
| 501 ASSERT(is_paused_on_exit_); | 501 ASSERT(is_paused_on_exit_); |
| 502 is_paused_on_exit_ = false; | 502 is_paused_on_exit_ = false; |
| 503 paused_timestamp_ = -1; | 503 paused_timestamp_ = -1; |
| 504 } | 504 } |
| 505 if (is_paused_on_exit_) { | 505 if (is_paused_on_exit_) { |
| 506 // Temporarily release the monitor when calling out to | 506 // Temporarily release the monitor when calling out to |
| 507 // NotifyPauseOnExit. This avoids a dead lock that can | 507 // NotifyPauseOnExit. This avoids a dead lock that can |
| 508 // occur when this message handler tries to post a message | 508 // occur when this message handler tries to post a message |
| 509 // while a message is being posted to it. | 509 // while a message is being posted to it. |
| 510 monitor_.Exit(); | 510 ml->Exit(); |
| 511 NotifyPauseOnExit(); | 511 NotifyPauseOnExit(); |
| 512 monitor_.Enter(); | 512 ml->Enter(); |
| 513 } else { | 513 } else { |
| 514 // Resumed. Clear the resume request of the owning isolate. | 514 // Resumed. Clear the resume request of the owning isolate. |
| 515 Isolate* owning_isolate = isolate(); | 515 Isolate* owning_isolate = isolate(); |
| 516 if (owning_isolate != NULL) { | 516 if (owning_isolate != NULL) { |
| 517 owning_isolate->GetAndClearResumeRequest(); | 517 owning_isolate->GetAndClearResumeRequest(); |
| 518 } | 518 } |
| 519 } | 519 } |
| 520 } | 520 } |
| 521 | 521 |
| 522 | 522 |
| 523 MessageHandler::AcquiredQueues::AcquiredQueues() | 523 MessageHandler::AcquiredQueues::AcquiredQueues(MessageHandler* handler) |
| 524 : handler_(NULL) { | 524 : handler_(handler), ml_(&handler->monitor_) { |
| 525 ASSERT(handler != NULL); |
| 526 handler_->oob_message_handling_allowed_ = false; |
| 525 } | 527 } |
| 526 | 528 |
| 527 | 529 |
| 528 MessageHandler::AcquiredQueues::~AcquiredQueues() { | 530 MessageHandler::AcquiredQueues::~AcquiredQueues() { |
| 529 Reset(NULL); | |
| 530 } | |
| 531 | |
| 532 | |
| 533 void MessageHandler::AcquiredQueues::Reset(MessageHandler* handler) { | |
| 534 if (handler_ != NULL) { | |
| 535 // Release ownership. The OOB flag is set without holding the monitor. | |
| 536 handler_->monitor_.Exit(); | |
| 537 handler_->oob_message_handling_allowed_ = true; | |
| 538 } | |
| 539 handler_ = handler; | |
| 540 if (handler_ == NULL) { | |
| 541 return; | |
| 542 } | |
| 543 ASSERT(handler_ != NULL); | 531 ASSERT(handler_ != NULL); |
| 544 // Take ownership. The OOB flag is set without holding the monitor. | 532 handler_->oob_message_handling_allowed_ = true; |
| 545 handler_->oob_message_handling_allowed_ = false; | |
| 546 handler_->monitor_.Enter(); | |
| 547 } | |
| 548 | |
| 549 | |
| 550 void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) { | |
| 551 ASSERT(acquired_queues != NULL); | |
| 552 // No double dipping. | |
| 553 ASSERT(acquired_queues->handler_ == NULL); | |
| 554 acquired_queues->Reset(this); | |
| 555 } | 533 } |
| 556 | 534 |
| 557 } // namespace dart | 535 } // namespace dart |
| OLD | NEW |