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

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

Issue 1259223005: Safepoint interface and unit tests. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Add comment about overflow. 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
« no previous file with comments | « runtime/vm/thread_registry.cc ('k') | runtime/vm/vm_sources.gypi » ('j') | 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 "platform/assert.h" 5 #include "platform/assert.h"
6 #include "vm/isolate.h" 6 #include "vm/isolate.h"
7 #include "vm/lockers.h" 7 #include "vm/lockers.h"
8 #include "vm/unit_test.h" 8 #include "vm/unit_test.h"
9 #include "vm/profiler.h" 9 #include "vm/profiler.h"
10 #include "vm/thread_pool.h" 10 #include "vm/thread_pool.h"
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 isos[1]->Shutdown(); 217 isos[1]->Shutdown();
218 Thread::ExitIsolate(); 218 Thread::ExitIsolate();
219 Thread::EnterIsolate(orig); 219 Thread::EnterIsolate(orig);
220 // Original zone should be preserved. 220 // Original zone should be preserved.
221 EXPECT_EQ(orig_zone, Thread::Current()->zone()); 221 EXPECT_EQ(orig_zone, Thread::Current()->zone());
222 EXPECT_STREQ("foo", orig_str); 222 EXPECT_STREQ("foo", orig_str);
223 delete isos[0]; 223 delete isos[0];
224 delete isos[1]; 224 delete isos[1];
225 } 225 }
226 226
227
228 // A helper thread that alternatingly cooperates and organizes
229 // safepoint rendezvous. At rendezvous, it explicitly visits the
230 // stacks looking for a specific marker (Smi) to verify that the expected
231 // number threads are actually visited. The task is "done" when it has
232 // successfully made all other tasks and the main thread rendezvous (may
233 // not happen in the first rendezvous, since tasks are still starting up).
234 class SafepointTestTask : public ThreadPool::Task {
235 public:
236 static const intptr_t kTaskCount;
237
238 SafepointTestTask(Isolate* isolate,
239 Mutex* mutex,
240 intptr_t* expected_count,
241 intptr_t* total_done,
242 intptr_t* exited)
243 : isolate_(isolate),
244 mutex_(mutex),
245 expected_count_(expected_count),
246 total_done_(total_done),
247 exited_(exited),
248 local_done_(false) {}
249
250 virtual void Run() {
251 Thread::EnterIsolateAsHelper(isolate_);
252 {
253 MutexLocker ml(mutex_);
254 ++*expected_count_;
255 }
256 for (int i = 0; ; ++i) {
257 Thread* thread = Thread::Current();
258 StackZone stack_zone(thread);
259 Zone* zone = thread->zone();
zra 2015/08/01 03:28:22 DBC Extra indent.
koda 2015/08/01 06:06:52 Done in follow up CL.
260 HANDLESCOPE(thread);
261 const intptr_t kUniqueSmi = 928327281;
262 Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi));
263 if ((i % 100) != 0) {
264 // Usually, we just cooperate.
265 isolate_->thread_registry()->CheckSafepoint();
266 } else {
267 // But occasionally, organize a rendezvous.
268 isolate_->thread_registry()->SafepointThreads();
269 ObjectCounter counter(isolate_, &smi);
270 isolate_->thread_registry()->VisitObjectPointers(&counter);
271 {
272 MutexLocker ml(mutex_);
273 EXPECT_EQ(*expected_count_, counter.count());
274 }
275 UserTag& tag = UserTag::Handle(zone, isolate_->current_tag());
276 if (tag.raw() != isolate_->default_tag()) {
277 String& label = String::Handle(zone, tag.label());
278 EXPECT(label.Equals("foo"));
279 // if this is the first time.
280 MutexLocker ml(mutex_);
281 if (*expected_count_ == kTaskCount && !local_done_) {
282 // Success for the first time! Remember that we are done, and
283 // update the total count.
284 local_done_ = true;
285 ++*total_done_;
286 }
287 }
288 isolate_->thread_registry()->ResumeAllThreads();
289 }
290 // Check whether everyone is done.
291 {
292 MutexLocker ml(mutex_);
293 if (*total_done_ == kTaskCount) {
294 break;
295 }
296 }
297 }
298 Thread::ExitIsolateAsHelper();
299 {
300 MutexLocker ml(mutex_);
301 ++*exited_;
302 }
303 }
304
305 private:
306 Isolate* isolate_;
307 Mutex* mutex_;
308 intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit.
309 intptr_t* total_done_; // # tasks that successfully safepointed once.
310 intptr_t* exited_; // # tasks that are no longer running.
311 bool local_done_; // this task has successfully safepointed >= once.
312 };
313
314
315 const intptr_t SafepointTestTask::kTaskCount = 5;
316
317
318 // Test rendezvous of:
319 // - helpers in VM code,
320 // - main thread in pure Dart,
321 // organized by
322 // - helpers.
323 TEST_CASE(SafepointTestDart) {
324 Isolate* isolate = Thread::Current()->isolate();
325 Mutex mutex;
326 intptr_t expected_count = 0;
327 intptr_t total_done = 0;
328 intptr_t exited = 0;
329 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
330 Dart::thread_pool()->Run(new SafepointTestTask(
331 isolate, &mutex, &expected_count, &total_done, &exited));
332 }
333 // Run Dart code on the main thread long enough to allow all helpers
334 // to get their verification done and exit. Use a specific UserTag
335 // to enable the helpers to verify that the main thread is
336 // successfully interrupted in the pure Dart loop.
337 #if defined(USING_SIMULATOR)
338 const intptr_t kLoopCount = 12345678;
339 #else
340 const intptr_t kLoopCount = 1234567890;
341 #endif // USING_SIMULATOR
342 char buffer[1024];
343 OS::SNPrint(buffer, sizeof(buffer),
344 "import 'dart:profiler';\n"
345 "int dummy = 0;\n"
346 "main() {\n"
347 " new UserTag('foo').makeCurrent();\n"
348 " for (dummy = 0; dummy < %" Pd "; ++dummy) {\n"
349 " dummy += (dummy & 1);\n"
350 " }\n"
351 "}\n", kLoopCount);
352 Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
353 EXPECT_VALID(lib);
354 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
355 EXPECT_VALID(result);
356 // Ensure we looped long enough to allow all helpers to succeed and exit.
357 {
358 MutexLocker ml(&mutex);
359 EXPECT_EQ(SafepointTestTask::kTaskCount, total_done);
360 EXPECT_EQ(SafepointTestTask::kTaskCount, exited);
361 }
362 }
363
364
365 // Test rendezvous of:
366 // - helpers in VM code, and
367 // - main thread in VM code,
368 // organized by
369 // - helpers.
370 TEST_CASE(SafepointTestVM) {
371 Thread* thread = Thread::Current();
372 Isolate* isolate = thread->isolate();
373 Mutex mutex;
374 intptr_t expected_count = 0;
375 intptr_t total_done = 0;
376 intptr_t exited = 0;
377 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
378 Dart::thread_pool()->Run(new SafepointTestTask(
379 isolate, &mutex, &expected_count, &total_done, &exited));
380 }
381 String& label = String::Handle(String::New("foo"));
382 UserTag& tag = UserTag::Handle(UserTag::New(label));
383 isolate->set_current_tag(tag);
384 while (true) {
385 isolate->thread_registry()->CheckSafepoint();
386 MutexLocker ml(&mutex);
387 if (exited == SafepointTestTask::kTaskCount) {
388 break;
389 }
390 }
391 }
392
393
394 // Test rendezvous of:
395 // - helpers in VM code, and
396 // - main thread in VM code,
397 // organized by
398 // - main thread, and
399 // - helpers.
400 TEST_CASE(SafepointTestVM2) {
401 Thread* thread = Thread::Current();
402 Isolate* isolate = thread->isolate();
403 Mutex mutex;
404 intptr_t expected_count = 0;
405 intptr_t total_done = 0;
406 intptr_t exited = 0;
407 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
408 Dart::thread_pool()->Run(new SafepointTestTask(
409 isolate, &mutex, &expected_count, &total_done, &exited));
410 }
411 bool all_helpers = false;
412 do {
413 isolate->thread_registry()->SafepointThreads();
414 {
415 MutexLocker ml(&mutex);
416 if (expected_count == SafepointTestTask::kTaskCount) {
417 all_helpers = true;
418 }
419 }
420 isolate->thread_registry()->ResumeAllThreads();
421 } while (!all_helpers);
422 String& label = String::Handle(String::New("foo"));
423 UserTag& tag = UserTag::Handle(UserTag::New(label));
424 isolate->set_current_tag(tag);
425 while (true) {
426 isolate->thread_registry()->CheckSafepoint();
427 MutexLocker ml(&mutex);
428 if (exited == SafepointTestTask::kTaskCount) {
429 break;
430 }
431 }
432 }
433
227 } // namespace dart 434 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread_registry.cc ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698