| 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
 | 
| 
 |