| Index: runtime/vm/isolate_test.cc
|
| diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
|
| index 6000ee686e0885dc088107816341d5358a7d10db..8dcc14e8e750af9a5b717cf89bd4dbab1837377b 100644
|
| --- a/runtime/vm/isolate_test.cc
|
| +++ b/runtime/vm/isolate_test.cc
|
| @@ -7,6 +7,7 @@
|
| #include "vm/globals.h"
|
| #include "vm/isolate.h"
|
| #include "vm/lockers.h"
|
| +#include "vm/thread_barrier.h"
|
| #include "vm/thread_pool.h"
|
| #include "vm/unit_test.h"
|
|
|
| @@ -89,89 +90,36 @@ class InterruptChecker : public ThreadPool::Task {
|
| static const intptr_t kIterations;
|
|
|
| InterruptChecker(Isolate* isolate,
|
| - Monitor* awake_monitor,
|
| - bool* awake,
|
| - Monitor* round_monitor,
|
| - const intptr_t* round)
|
| + ThreadBarrier* barrier)
|
| : isolate_(isolate),
|
| - awake_monitor_(awake_monitor),
|
| - awake_(awake),
|
| - round_monitor_(round_monitor),
|
| - round_(round) {
|
| + barrier_(barrier) {
|
| }
|
|
|
| virtual void Run() {
|
| Thread::EnterIsolateAsHelper(isolate_);
|
| // Tell main thread that we are ready.
|
| - {
|
| - MonitorLocker ml(awake_monitor_);
|
| - ASSERT(!*awake_);
|
| - *awake_ = true;
|
| - ml.Notify();
|
| - }
|
| + barrier_->Sync();
|
| for (intptr_t i = 0; i < kIterations; ++i) {
|
| // Busy wait for interrupts.
|
| while (!isolate_->HasInterruptsScheduled(Isolate::kVMInterrupt)) {
|
| // Do nothing.
|
| }
|
| // Tell main thread that we observed the interrupt.
|
| - {
|
| - MonitorLocker ml(awake_monitor_);
|
| - ASSERT(!*awake_);
|
| - *awake_ = true;
|
| - ml.Notify();
|
| - }
|
| - // Wait for main thread to let us resume, i.e., until all tasks are here.
|
| - {
|
| - MonitorLocker ml(round_monitor_);
|
| - EXPECT(*round_ == i || *round_ == (i + 1));
|
| - while (*round_ == i) {
|
| - ml.Wait();
|
| - }
|
| - EXPECT(*round_ == i + 1);
|
| - }
|
| + barrier_->Sync();
|
| }
|
| Thread::ExitIsolateAsHelper();
|
| - // Use awake also to signal exit.
|
| - {
|
| - MonitorLocker ml(awake_monitor_);
|
| - *awake_ = true;
|
| - ml.Notify();
|
| - }
|
| + barrier_->Exit();
|
| }
|
|
|
| private:
|
| Isolate* isolate_;
|
| - Monitor* awake_monitor_;
|
| - bool* awake_;
|
| - Monitor* round_monitor_;
|
| - const intptr_t* round_;
|
| + ThreadBarrier* barrier_;
|
| };
|
|
|
|
|
| const intptr_t InterruptChecker::kTaskCount = 5;
|
| const intptr_t InterruptChecker::kIterations = 10;
|
|
|
| -
|
| -// Waits for all tasks to set their individual flag, then clears them all.
|
| -static void WaitForAllTasks(bool* flags, Monitor* monitor) {
|
| - MonitorLocker ml(monitor);
|
| - while (true) {
|
| - intptr_t count = 0;
|
| - for (intptr_t task = 0; task < InterruptChecker::kTaskCount; ++task) {
|
| - if (flags[task]) {
|
| - ++count;
|
| - }
|
| - }
|
| - if (count == InterruptChecker::kTaskCount) {
|
| - memset(flags, 0, sizeof(*flags) * count);
|
| - break;
|
| - } else {
|
| - ml.Wait();
|
| - }
|
| - }
|
| -}
|
| -
|
| // Test and document usage of Isolate::HasInterruptsScheduled.
|
| //
|
| // Go through a number of rounds of scheduling interrupts and waiting until all
|
| @@ -182,34 +130,23 @@ static void WaitForAllTasks(bool* flags, Monitor* monitor) {
|
| // compiler and/or CPU could reorder operations to make the tasks observe the
|
| // round update *before* the interrupt is set.
|
| TEST_CASE(StackLimitInterrupts) {
|
| - Monitor awake_monitor; // Synchronizes the 'awake' flags.
|
| - bool awake[InterruptChecker::kTaskCount];
|
| - memset(awake, 0, sizeof(awake));
|
| - Monitor round_monitor; // Synchronizes the 'round' counter.
|
| - intptr_t round = 0;
|
| Isolate* isolate = Thread::Current()->isolate();
|
| + ThreadBarrier barrier(InterruptChecker::kTaskCount + 1);
|
| // Start all tasks. They will busy-wait until interrupted in the first round.
|
| for (intptr_t task = 0; task < InterruptChecker::kTaskCount; task++) {
|
| - Dart::thread_pool()->Run(new InterruptChecker(
|
| - isolate, &awake_monitor, &awake[task], &round_monitor, &round));
|
| + Dart::thread_pool()->Run(new InterruptChecker(isolate, &barrier));
|
| }
|
| // Wait for all tasks to get ready for the first round.
|
| - WaitForAllTasks(awake, &awake_monitor);
|
| + barrier.Sync();
|
| for (intptr_t i = 0; i < InterruptChecker::kIterations; ++i) {
|
| isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
|
| // Wait for all tasks to observe the interrupt.
|
| - WaitForAllTasks(awake, &awake_monitor);
|
| + barrier.Sync();
|
| // Continue with next round.
|
| uword interrupts = isolate->GetAndClearInterrupts();
|
| EXPECT((interrupts & Isolate::kVMInterrupt) != 0);
|
| - {
|
| - MonitorLocker ml(&round_monitor);
|
| - ++round;
|
| - ml.NotifyAll();
|
| - }
|
| }
|
| - // Wait for tasks to exit cleanly.
|
| - WaitForAllTasks(awake, &awake_monitor);
|
| + barrier.Exit();
|
| }
|
|
|
| } // namespace dart
|
|
|