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

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

Issue 1277473004: Safe and efficient stack-limit based interrupt checking in C++. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Comments. Created 5 years, 4 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
« runtime/vm/atomic_win.h ('K') | « runtime/vm/isolate.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "include/dart_api.h" 5 #include "include/dart_api.h"
6 #include "platform/assert.h" 6 #include "platform/assert.h"
7 #include "vm/globals.h" 7 #include "vm/globals.h"
8 #include "vm/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/lockers.h"
10 #include "vm/thread_pool.h"
9 #include "vm/unit_test.h" 11 #include "vm/unit_test.h"
10 12
11 namespace dart { 13 namespace dart {
12 14
13 UNIT_TEST_CASE(IsolateCurrent) { 15 UNIT_TEST_CASE(IsolateCurrent) {
14 Dart_Isolate isolate = Dart_CreateIsolate( 16 Dart_Isolate isolate = Dart_CreateIsolate(
15 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); 17 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
16 EXPECT_EQ(isolate, Dart_CurrentIsolate()); 18 EXPECT_EQ(isolate, Dart_CurrentIsolate());
17 Dart_ShutdownIsolate(); 19 Dart_ShutdownIsolate();
18 EXPECT_EQ(reinterpret_cast<Dart_Isolate>(NULL), Dart_CurrentIsolate()); 20 EXPECT_EQ(reinterpret_cast<Dart_Isolate>(NULL), Dart_CurrentIsolate());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 result = Dart_Invoke(test_lib, NewString("testMain"), 0, NULL); 75 result = Dart_Invoke(test_lib, NewString("testMain"), 0, NULL);
74 EXPECT(!Dart_IsError(result)); 76 EXPECT(!Dart_IsError(result));
75 // Run until all ports to isolate are closed. 77 // Run until all ports to isolate are closed.
76 result = Dart_RunLoop(); 78 result = Dart_RunLoop();
77 EXPECT_ERROR(result, "Null callback specified for isolate creation"); 79 EXPECT_ERROR(result, "Null callback specified for isolate creation");
78 EXPECT(Dart_ErrorHasException(result)); 80 EXPECT(Dart_ErrorHasException(result));
79 Dart_Handle exception_result = Dart_ErrorGetException(result); 81 Dart_Handle exception_result = Dart_ErrorGetException(result);
80 EXPECT_VALID(exception_result); 82 EXPECT_VALID(exception_result);
81 } 83 }
82 84
85
86 class InterruptChecker : public ThreadPool::Task {
87 public:
88 static const intptr_t kTaskCount;
89 static const intptr_t kIterations;
90
91 InterruptChecker(Isolate* isolate,
92 Monitor* monitor,
93 bool* awake,
94 Monitor* round_monitor,
95 const intptr_t* round)
96 : isolate_(isolate),
97 monitor_(monitor),
98 awake_(awake),
99 round_monitor_(round_monitor),
100 round_(round) {
101 }
102
103 virtual void Run() {
104 Thread::EnterIsolateAsHelper(isolate_);
105 for (intptr_t i = 0; i < kIterations; ++i) {
106 // Busy wait for interrupts.
107 while (!isolate_->HasInterruptsScheduled(Isolate::kVMInterrupt)) {
108 // Do nothing.
109 }
110 // Tell main thread that we observed the interrupt.
111 {
112 MonitorLocker ml(monitor_);
113 ASSERT(!*awake_);
114 *awake_ = true;
115 ml.Notify();
116 }
117 // Wait for main thread to let us resume.
118 {
119 MonitorLocker ml(round_monitor_);
120 EXPECT(*round_ == i || *round_ == (i + 1));
121 while (*round_ == i) {
122 ml.Wait();
123 }
124 EXPECT(*round_ == i + 1);
125 }
126 }
127 Thread::ExitIsolateAsHelper();
128 // Use awake to signal exit.
129 {
130 MonitorLocker ml(monitor_);
131 *awake_ = true;
132 ml.Notify();
133 }
134 }
135
136 private:
137 Isolate* isolate_;
138 Monitor* monitor_;
139 bool* awake_;
140 Monitor* round_monitor_;
141 const intptr_t* round_;
142 };
143
144
145 const intptr_t InterruptChecker::kTaskCount = 50;
146 const intptr_t InterruptChecker::kIterations = 1000;
147
148
149 // Waits for all tasks to set their flag, then clears them all.
150 static void WaitForAllTasks(bool* flags, Monitor* monitor) {
151 MonitorLocker ml(monitor);
152 while (true) {
153 intptr_t count = 0;
154 for (intptr_t task = 0; task < InterruptChecker::kTaskCount; ++task) {
155 if (flags[task]) {
156 ++count;
157 }
158 }
159 if (count == InterruptChecker::kTaskCount) {
160 memset(flags, 0, sizeof(*flags) * count);
161 break;
162 } else {
163 ml.Wait();
164 }
165 }
166 }
167
168 // Test and document usage of Isolate::HasInterruptsScheduled.
169 //
170 // Go through a number of rounds of scheduling interrupts and waiting until all
171 // unsynchronized busy-waiting tasks observe it (in the current implementation,
172 // the exact latency depends on cache coherence). Synchronization is then used
173 // to enforce the required memory ordering, to ensure correct progression of
174 // the rounds.
175 TEST_CASE(StackLimitInterrupts) {
176 Monitor monitor;
177 bool awake[InterruptChecker::kTaskCount];
178 memset(awake, 0, sizeof(awake));
179 Monitor round_monitor;
180 intptr_t round = 0;
181 Isolate* isolate = Thread::Current()->isolate();
182 for (intptr_t task = 0; task < InterruptChecker::kTaskCount; task++) {
183 Dart::thread_pool()->Run(new InterruptChecker(
184 isolate, &monitor, &awake[task], &round_monitor, &round));
185 }
186 for (intptr_t i = 0; i < InterruptChecker::kIterations; ++i) {
187 isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
188 WaitForAllTasks(awake, &monitor);
189 uword interrupts = isolate->GetAndClearInterrupts();
190 EXPECT((interrupts & Isolate::kVMInterrupt) != 0);
191 {
192 MonitorLocker ml(&round_monitor);
193 ++round;
194 ml.NotifyAll();
195 }
196 }
197 // Wait for tasks to exit cleanly.
198 WaitForAllTasks(awake, &monitor);
199 }
200
83 } // namespace dart 201 } // namespace dart
OLDNEW
« runtime/vm/atomic_win.h ('K') | « runtime/vm/isolate.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698