| OLD | NEW |
| 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" | |
| 9 #include "vm/profiler.h" | 8 #include "vm/profiler.h" |
| 10 #include "vm/safepoint.h" | 9 #include "vm/safepoint.h" |
| 11 #include "vm/stack_frame.h" | 10 #include "vm/stack_frame.h" |
| 12 #include "vm/thread_pool.h" | 11 #include "vm/thread_pool.h" |
| 12 #include "vm/unit_test.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 VM_UNIT_TEST_CASE(Mutex) { | 16 VM_UNIT_TEST_CASE(Mutex) { |
| 17 // This unit test case needs a running isolate. | 17 // This unit test case needs a running isolate. |
| 18 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, | 18 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, |
| 19 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); | 19 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); |
| 20 | 20 |
| 21 Mutex* mutex = new Mutex(); | 21 Mutex* mutex = new Mutex(); |
| 22 mutex->Lock(); | 22 mutex->Lock(); |
| 23 EXPECT_EQ(false, mutex->TryLock()); | 23 EXPECT_EQ(false, mutex->TryLock()); |
| 24 mutex->Unlock(); | 24 mutex->Unlock(); |
| 25 EXPECT_EQ(true, mutex->TryLock()); | 25 EXPECT_EQ(true, mutex->TryLock()); |
| 26 mutex->Unlock(); | 26 mutex->Unlock(); |
| 27 { | 27 { |
| 28 MutexLocker ml(mutex); | 28 MutexLocker ml(mutex); |
| 29 EXPECT_EQ(false, mutex->TryLock()); | 29 EXPECT_EQ(false, mutex->TryLock()); |
| 30 } | 30 } |
| 31 // The isolate shutdown and the destruction of the mutex are out-of-order on | 31 // The isolate shutdown and the destruction of the mutex are out-of-order on |
| 32 // purpose. | 32 // purpose. |
| 33 Dart_ShutdownIsolate(); | 33 Dart_ShutdownIsolate(); |
| 34 delete mutex; | 34 delete mutex; |
| 35 } | 35 } |
| 36 | 36 |
| 37 | |
| 38 VM_UNIT_TEST_CASE(Monitor) { | 37 VM_UNIT_TEST_CASE(Monitor) { |
| 39 // This unit test case needs a running isolate. | 38 // This unit test case needs a running isolate. |
| 40 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, | 39 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, |
| 41 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); | 40 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); |
| 42 OSThread* thread = OSThread::Current(); | 41 OSThread* thread = OSThread::Current(); |
| 43 // Thread interrupter interferes with this test, disable interrupts. | 42 // Thread interrupter interferes with this test, disable interrupts. |
| 44 thread->DisableThreadInterrupts(); | 43 thread->DisableThreadInterrupts(); |
| 45 Monitor* monitor = new Monitor(); | 44 Monitor* monitor = new Monitor(); |
| 46 monitor->Enter(); | 45 monitor->Enter(); |
| 47 monitor->Exit(); | 46 monitor->Exit(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 74 attempts++; | 73 attempts++; |
| 75 } | 74 } |
| 76 EXPECT_LT(attempts, kNumAttempts); | 75 EXPECT_LT(attempts, kNumAttempts); |
| 77 | 76 |
| 78 // The isolate shutdown and the destruction of the mutex are out-of-order on | 77 // The isolate shutdown and the destruction of the mutex are out-of-order on |
| 79 // purpose. | 78 // purpose. |
| 80 Dart_ShutdownIsolate(); | 79 Dart_ShutdownIsolate(); |
| 81 delete monitor; | 80 delete monitor; |
| 82 } | 81 } |
| 83 | 82 |
| 84 | |
| 85 class ObjectCounter : public ObjectPointerVisitor { | 83 class ObjectCounter : public ObjectPointerVisitor { |
| 86 public: | 84 public: |
| 87 explicit ObjectCounter(Isolate* isolate, const Object* obj) | 85 explicit ObjectCounter(Isolate* isolate, const Object* obj) |
| 88 : ObjectPointerVisitor(isolate), obj_(obj), count_(0) {} | 86 : ObjectPointerVisitor(isolate), obj_(obj), count_(0) {} |
| 89 | 87 |
| 90 virtual void VisitPointers(RawObject** first, RawObject** last) { | 88 virtual void VisitPointers(RawObject** first, RawObject** last) { |
| 91 for (RawObject** current = first; current <= last; ++current) { | 89 for (RawObject** current = first; current <= last; ++current) { |
| 92 if (*current == obj_->raw()) { | 90 if (*current == obj_->raw()) { |
| 93 ++count_; | 91 ++count_; |
| 94 } | 92 } |
| 95 } | 93 } |
| 96 } | 94 } |
| 97 | 95 |
| 98 intptr_t count() const { return count_; } | 96 intptr_t count() const { return count_; } |
| 99 | 97 |
| 100 private: | 98 private: |
| 101 const Object* obj_; | 99 const Object* obj_; |
| 102 intptr_t count_; | 100 intptr_t count_; |
| 103 }; | 101 }; |
| 104 | 102 |
| 105 | |
| 106 class TaskWithZoneAllocation : public ThreadPool::Task { | 103 class TaskWithZoneAllocation : public ThreadPool::Task { |
| 107 public: | 104 public: |
| 108 TaskWithZoneAllocation(Isolate* isolate, | 105 TaskWithZoneAllocation(Isolate* isolate, |
| 109 Monitor* monitor, | 106 Monitor* monitor, |
| 110 bool* done, | 107 bool* done, |
| 111 intptr_t id) | 108 intptr_t id) |
| 112 : isolate_(isolate), monitor_(monitor), done_(done), id_(id) {} | 109 : isolate_(isolate), monitor_(monitor), done_(done), id_(id) {} |
| 113 virtual void Run() { | 110 virtual void Run() { |
| 114 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); | 111 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); |
| 115 { | 112 { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 162 } |
| 166 } | 163 } |
| 167 | 164 |
| 168 private: | 165 private: |
| 169 Isolate* isolate_; | 166 Isolate* isolate_; |
| 170 Monitor* monitor_; | 167 Monitor* monitor_; |
| 171 bool* done_; | 168 bool* done_; |
| 172 intptr_t id_; | 169 intptr_t id_; |
| 173 }; | 170 }; |
| 174 | 171 |
| 175 | |
| 176 ISOLATE_UNIT_TEST_CASE(ManyTasksWithZones) { | 172 ISOLATE_UNIT_TEST_CASE(ManyTasksWithZones) { |
| 177 const int kTaskCount = 100; | 173 const int kTaskCount = 100; |
| 178 Monitor sync[kTaskCount]; | 174 Monitor sync[kTaskCount]; |
| 179 bool done[kTaskCount]; | 175 bool done[kTaskCount]; |
| 180 Isolate* isolate = Thread::Current()->isolate(); | 176 Isolate* isolate = Thread::Current()->isolate(); |
| 181 EXPECT(isolate->heap()->GrowthControlState()); | 177 EXPECT(isolate->heap()->GrowthControlState()); |
| 182 isolate->heap()->DisableGrowthControl(); | 178 isolate->heap()->DisableGrowthControl(); |
| 183 for (int i = 0; i < kTaskCount; i++) { | 179 for (int i = 0; i < kTaskCount; i++) { |
| 184 done[i] = false; | 180 done[i] = false; |
| 185 Dart::thread_pool()->Run( | 181 Dart::thread_pool()->Run( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 197 ml.Wait(); | 193 ml.Wait(); |
| 198 } | 194 } |
| 199 EXPECT(done[i]); | 195 EXPECT(done[i]); |
| 200 if (i % 10 == 0) { | 196 if (i % 10 == 0) { |
| 201 Thread::EnterIsolate(isolate); | 197 Thread::EnterIsolate(isolate); |
| 202 } | 198 } |
| 203 EXPECT(bar.Equals("bar")); | 199 EXPECT(bar.Equals("bar")); |
| 204 } | 200 } |
| 205 } | 201 } |
| 206 | 202 |
| 207 | |
| 208 #ifndef PRODUCT | 203 #ifndef PRODUCT |
| 209 class SimpleTaskWithZoneAllocation : public ThreadPool::Task { | 204 class SimpleTaskWithZoneAllocation : public ThreadPool::Task { |
| 210 public: | 205 public: |
| 211 SimpleTaskWithZoneAllocation(intptr_t id, | 206 SimpleTaskWithZoneAllocation(intptr_t id, |
| 212 Isolate* isolate, | 207 Isolate* isolate, |
| 213 Thread** thread_ptr, | 208 Thread** thread_ptr, |
| 214 Monitor* sync, | 209 Monitor* sync, |
| 215 Monitor* monitor, | 210 Monitor* monitor, |
| 216 intptr_t* done_count, | 211 intptr_t* done_count, |
| 217 bool* wait) | 212 bool* wait) |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 | 274 |
| 280 intptr_t id_; | 275 intptr_t id_; |
| 281 Isolate* isolate_; | 276 Isolate* isolate_; |
| 282 Thread** thread_ptr_; | 277 Thread** thread_ptr_; |
| 283 Monitor* sync_; | 278 Monitor* sync_; |
| 284 Monitor* monitor_; | 279 Monitor* monitor_; |
| 285 intptr_t* done_count_; | 280 intptr_t* done_count_; |
| 286 bool* wait_; | 281 bool* wait_; |
| 287 }; | 282 }; |
| 288 | 283 |
| 289 | |
| 290 TEST_CASE(ManySimpleTasksWithZones) { | 284 TEST_CASE(ManySimpleTasksWithZones) { |
| 291 const int kTaskCount = 10; | 285 const int kTaskCount = 10; |
| 292 Monitor monitor; | 286 Monitor monitor; |
| 293 Monitor sync; | 287 Monitor sync; |
| 294 Thread* threads[kTaskCount]; | 288 Thread* threads[kTaskCount]; |
| 295 Isolate* isolate = Thread::Current()->isolate(); | 289 Isolate* isolate = Thread::Current()->isolate(); |
| 296 intptr_t done_count = 0; | 290 intptr_t done_count = 0; |
| 297 bool wait = true; | 291 bool wait = true; |
| 298 | 292 |
| 299 EXPECT(isolate->heap()->GrowthControlState()); | 293 EXPECT(isolate->heap()->GrowthControlState()); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 // Now wait for them all to exit before destroying the isolate. | 346 // Now wait for them all to exit before destroying the isolate. |
| 353 { | 347 { |
| 354 MonitorLocker ml(&monitor); | 348 MonitorLocker ml(&monitor); |
| 355 while (done_count < kTaskCount) { | 349 while (done_count < kTaskCount) { |
| 356 ml.Wait(); | 350 ml.Wait(); |
| 357 } | 351 } |
| 358 } | 352 } |
| 359 } | 353 } |
| 360 #endif | 354 #endif |
| 361 | 355 |
| 362 | |
| 363 TEST_CASE(ThreadRegistry) { | 356 TEST_CASE(ThreadRegistry) { |
| 364 Isolate* orig = Thread::Current()->isolate(); | 357 Isolate* orig = Thread::Current()->isolate(); |
| 365 Zone* orig_zone = Thread::Current()->zone(); | 358 Zone* orig_zone = Thread::Current()->zone(); |
| 366 char* orig_str = orig_zone->PrintToString("foo"); | 359 char* orig_str = orig_zone->PrintToString("foo"); |
| 367 Dart_ExitIsolate(); | 360 Dart_ExitIsolate(); |
| 368 // Create and enter a new isolate. | 361 // Create and enter a new isolate. |
| 369 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, | 362 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, |
| 370 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); | 363 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); |
| 371 Zone* zone0 = Thread::Current()->zone(); | 364 Zone* zone0 = Thread::Current()->zone(); |
| 372 EXPECT(zone0 != orig_zone); | 365 EXPECT(zone0 != orig_zone); |
| 373 Dart_ShutdownIsolate(); | 366 Dart_ShutdownIsolate(); |
| 374 // Create and enter yet another isolate. | 367 // Create and enter yet another isolate. |
| 375 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, | 368 Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data, |
| 376 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); | 369 bin::core_isolate_snapshot_instructions, NULL, NULL, NULL); |
| 377 { | 370 { |
| 378 // Create a stack resource this time, and exercise it. | 371 // Create a stack resource this time, and exercise it. |
| 379 StackZone stack_zone(Thread::Current()); | 372 StackZone stack_zone(Thread::Current()); |
| 380 Zone* zone1 = Thread::Current()->zone(); | 373 Zone* zone1 = Thread::Current()->zone(); |
| 381 EXPECT(zone1 != zone0); | 374 EXPECT(zone1 != zone0); |
| 382 EXPECT(zone1 != orig_zone); | 375 EXPECT(zone1 != orig_zone); |
| 383 } | 376 } |
| 384 Dart_ShutdownIsolate(); | 377 Dart_ShutdownIsolate(); |
| 385 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(orig)); | 378 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(orig)); |
| 386 // Original zone should be preserved. | 379 // Original zone should be preserved. |
| 387 EXPECT_EQ(orig_zone, Thread::Current()->zone()); | 380 EXPECT_EQ(orig_zone, Thread::Current()->zone()); |
| 388 EXPECT_STREQ("foo", orig_str); | 381 EXPECT_STREQ("foo", orig_str); |
| 389 } | 382 } |
| 390 | 383 |
| 391 | |
| 392 // A helper thread that alternatingly cooperates and organizes | 384 // A helper thread that alternatingly cooperates and organizes |
| 393 // safepoint rendezvous. At rendezvous, it explicitly visits the | 385 // safepoint rendezvous. At rendezvous, it explicitly visits the |
| 394 // stacks looking for a specific marker (Smi) to verify that the expected | 386 // stacks looking for a specific marker (Smi) to verify that the expected |
| 395 // number threads are actually visited. The task is "done" when it has | 387 // number threads are actually visited. The task is "done" when it has |
| 396 // successfully made all other tasks and the main thread rendezvous (may | 388 // successfully made all other tasks and the main thread rendezvous (may |
| 397 // not happen in the first rendezvous, since tasks are still starting up). | 389 // not happen in the first rendezvous, since tasks are still starting up). |
| 398 class SafepointTestTask : public ThreadPool::Task { | 390 class SafepointTestTask : public ThreadPool::Task { |
| 399 public: | 391 public: |
| 400 static const intptr_t kTaskCount; | 392 static const intptr_t kTaskCount; |
| 401 | 393 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 | 463 |
| 472 private: | 464 private: |
| 473 Isolate* isolate_; | 465 Isolate* isolate_; |
| 474 Monitor* monitor_; | 466 Monitor* monitor_; |
| 475 intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit. | 467 intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit. |
| 476 intptr_t* total_done_; // # tasks that successfully safepointed once. | 468 intptr_t* total_done_; // # tasks that successfully safepointed once. |
| 477 intptr_t* exited_; // # tasks that are no longer running. | 469 intptr_t* exited_; // # tasks that are no longer running. |
| 478 bool local_done_; // this task has successfully safepointed >= once. | 470 bool local_done_; // this task has successfully safepointed >= once. |
| 479 }; | 471 }; |
| 480 | 472 |
| 481 | |
| 482 const intptr_t SafepointTestTask::kTaskCount = 5; | 473 const intptr_t SafepointTestTask::kTaskCount = 5; |
| 483 | 474 |
| 484 | |
| 485 // Test rendezvous of: | 475 // Test rendezvous of: |
| 486 // - helpers in VM code, | 476 // - helpers in VM code, |
| 487 // - main thread in pure Dart, | 477 // - main thread in pure Dart, |
| 488 // organized by | 478 // organized by |
| 489 // - helpers. | 479 // - helpers. |
| 490 TEST_CASE(SafepointTestDart) { | 480 TEST_CASE(SafepointTestDart) { |
| 491 Isolate* isolate = Thread::Current()->isolate(); | 481 Isolate* isolate = Thread::Current()->isolate(); |
| 492 Monitor monitor; | 482 Monitor monitor; |
| 493 intptr_t expected_count = 0; | 483 intptr_t expected_count = 0; |
| 494 intptr_t total_done = 0; | 484 intptr_t total_done = 0; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 { | 516 { |
| 527 MonitorLocker ml(&monitor); | 517 MonitorLocker ml(&monitor); |
| 528 while (exited != SafepointTestTask::kTaskCount) { | 518 while (exited != SafepointTestTask::kTaskCount) { |
| 529 ml.Wait(); | 519 ml.Wait(); |
| 530 } | 520 } |
| 531 EXPECT_EQ(SafepointTestTask::kTaskCount, total_done); | 521 EXPECT_EQ(SafepointTestTask::kTaskCount, total_done); |
| 532 EXPECT_EQ(SafepointTestTask::kTaskCount, exited); | 522 EXPECT_EQ(SafepointTestTask::kTaskCount, exited); |
| 533 } | 523 } |
| 534 } | 524 } |
| 535 | 525 |
| 536 | |
| 537 // Test rendezvous of: | 526 // Test rendezvous of: |
| 538 // - helpers in VM code, and | 527 // - helpers in VM code, and |
| 539 // - main thread in VM code, | 528 // - main thread in VM code, |
| 540 // organized by | 529 // organized by |
| 541 // - helpers. | 530 // - helpers. |
| 542 ISOLATE_UNIT_TEST_CASE(SafepointTestVM) { | 531 ISOLATE_UNIT_TEST_CASE(SafepointTestVM) { |
| 543 Isolate* isolate = thread->isolate(); | 532 Isolate* isolate = thread->isolate(); |
| 544 Monitor monitor; | 533 Monitor monitor; |
| 545 intptr_t expected_count = 0; | 534 intptr_t expected_count = 0; |
| 546 intptr_t total_done = 0; | 535 intptr_t total_done = 0; |
| 547 intptr_t exited = 0; | 536 intptr_t exited = 0; |
| 548 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { | 537 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { |
| 549 Dart::thread_pool()->Run(new SafepointTestTask( | 538 Dart::thread_pool()->Run(new SafepointTestTask( |
| 550 isolate, &monitor, &expected_count, &total_done, &exited)); | 539 isolate, &monitor, &expected_count, &total_done, &exited)); |
| 551 } | 540 } |
| 552 String& label = String::Handle(String::New("foo")); | 541 String& label = String::Handle(String::New("foo")); |
| 553 UserTag& tag = UserTag::Handle(UserTag::New(label)); | 542 UserTag& tag = UserTag::Handle(UserTag::New(label)); |
| 554 isolate->set_current_tag(tag); | 543 isolate->set_current_tag(tag); |
| 555 MonitorLocker ml(&monitor); | 544 MonitorLocker ml(&monitor); |
| 556 while (exited != SafepointTestTask::kTaskCount) { | 545 while (exited != SafepointTestTask::kTaskCount) { |
| 557 ml.WaitWithSafepointCheck(thread); | 546 ml.WaitWithSafepointCheck(thread); |
| 558 } | 547 } |
| 559 } | 548 } |
| 560 | 549 |
| 561 | |
| 562 // Test case for recursive safepoint operations. | 550 // Test case for recursive safepoint operations. |
| 563 ISOLATE_UNIT_TEST_CASE(RecursiveSafepointTest1) { | 551 ISOLATE_UNIT_TEST_CASE(RecursiveSafepointTest1) { |
| 564 intptr_t count = 0; | 552 intptr_t count = 0; |
| 565 { | 553 { |
| 566 SafepointOperationScope safepoint_scope(thread); | 554 SafepointOperationScope safepoint_scope(thread); |
| 567 count += 1; | 555 count += 1; |
| 568 { | 556 { |
| 569 SafepointOperationScope safepoint_scope(thread); | 557 SafepointOperationScope safepoint_scope(thread); |
| 570 count += 1; | 558 count += 1; |
| 571 { | 559 { |
| 572 SafepointOperationScope safepoint_scope(thread); | 560 SafepointOperationScope safepoint_scope(thread); |
| 573 count += 1; | 561 count += 1; |
| 574 } | 562 } |
| 575 } | 563 } |
| 576 } | 564 } |
| 577 EXPECT(count == 3); | 565 EXPECT(count == 3); |
| 578 } | 566 } |
| 579 | 567 |
| 580 | |
| 581 ISOLATE_UNIT_TEST_CASE(ThreadIterator_Count) { | 568 ISOLATE_UNIT_TEST_CASE(ThreadIterator_Count) { |
| 582 intptr_t thread_count_0 = 0; | 569 intptr_t thread_count_0 = 0; |
| 583 intptr_t thread_count_1 = 0; | 570 intptr_t thread_count_1 = 0; |
| 584 | 571 |
| 585 { | 572 { |
| 586 OSThreadIterator ti; | 573 OSThreadIterator ti; |
| 587 while (ti.HasNext()) { | 574 while (ti.HasNext()) { |
| 588 OSThread* thread = ti.Next(); | 575 OSThread* thread = ti.Next(); |
| 589 EXPECT(thread != NULL); | 576 EXPECT(thread != NULL); |
| 590 thread_count_0++; | 577 thread_count_0++; |
| 591 } | 578 } |
| 592 } | 579 } |
| 593 | 580 |
| 594 { | 581 { |
| 595 OSThreadIterator ti; | 582 OSThreadIterator ti; |
| 596 while (ti.HasNext()) { | 583 while (ti.HasNext()) { |
| 597 OSThread* thread = ti.Next(); | 584 OSThread* thread = ti.Next(); |
| 598 EXPECT(thread != NULL); | 585 EXPECT(thread != NULL); |
| 599 thread_count_1++; | 586 thread_count_1++; |
| 600 } | 587 } |
| 601 } | 588 } |
| 602 | 589 |
| 603 EXPECT(thread_count_0 > 0); | 590 EXPECT(thread_count_0 > 0); |
| 604 EXPECT(thread_count_1 > 0); | 591 EXPECT(thread_count_1 > 0); |
| 605 EXPECT(thread_count_0 >= thread_count_1); | 592 EXPECT(thread_count_0 >= thread_count_1); |
| 606 } | 593 } |
| 607 | 594 |
| 608 | |
| 609 ISOLATE_UNIT_TEST_CASE(ThreadIterator_FindSelf) { | 595 ISOLATE_UNIT_TEST_CASE(ThreadIterator_FindSelf) { |
| 610 OSThread* current = OSThread::Current(); | 596 OSThread* current = OSThread::Current(); |
| 611 EXPECT(OSThread::IsThreadInList(current->id())); | 597 EXPECT(OSThread::IsThreadInList(current->id())); |
| 612 } | 598 } |
| 613 | 599 |
| 614 | |
| 615 struct ThreadIteratorTestParams { | 600 struct ThreadIteratorTestParams { |
| 616 ThreadId spawned_thread_id; | 601 ThreadId spawned_thread_id; |
| 617 ThreadJoinId spawned_thread_join_id; | 602 ThreadJoinId spawned_thread_join_id; |
| 618 Monitor* monitor; | 603 Monitor* monitor; |
| 619 }; | 604 }; |
| 620 | 605 |
| 621 | |
| 622 void ThreadIteratorTestMain(uword parameter) { | 606 void ThreadIteratorTestMain(uword parameter) { |
| 623 ThreadIteratorTestParams* params = | 607 ThreadIteratorTestParams* params = |
| 624 reinterpret_cast<ThreadIteratorTestParams*>(parameter); | 608 reinterpret_cast<ThreadIteratorTestParams*>(parameter); |
| 625 OSThread* thread = OSThread::Current(); | 609 OSThread* thread = OSThread::Current(); |
| 626 EXPECT(thread != NULL); | 610 EXPECT(thread != NULL); |
| 627 | 611 |
| 628 MonitorLocker ml(params->monitor); | 612 MonitorLocker ml(params->monitor); |
| 629 params->spawned_thread_id = thread->id(); | 613 params->spawned_thread_id = thread->id(); |
| 630 params->spawned_thread_join_id = OSThread::GetCurrentThreadJoinId(thread); | 614 params->spawned_thread_join_id = OSThread::GetCurrentThreadJoinId(thread); |
| 631 EXPECT(params->spawned_thread_id != OSThread::kInvalidThreadId); | 615 EXPECT(params->spawned_thread_id != OSThread::kInvalidThreadId); |
| 632 EXPECT(OSThread::IsThreadInList(thread->id())); | 616 EXPECT(OSThread::IsThreadInList(thread->id())); |
| 633 ml.Notify(); | 617 ml.Notify(); |
| 634 } | 618 } |
| 635 | 619 |
| 636 | |
| 637 // NOTE: This test case also verifies that known TLS destructors are called | 620 // NOTE: This test case also verifies that known TLS destructors are called |
| 638 // on Windows. See |OnDartThreadExit| in os_thread_win.cc for more details. | 621 // on Windows. See |OnDartThreadExit| in os_thread_win.cc for more details. |
| 639 TEST_CASE(ThreadIterator_AddFindRemove) { | 622 TEST_CASE(ThreadIterator_AddFindRemove) { |
| 640 ThreadIteratorTestParams params; | 623 ThreadIteratorTestParams params; |
| 641 params.spawned_thread_id = OSThread::kInvalidThreadId; | 624 params.spawned_thread_id = OSThread::kInvalidThreadId; |
| 642 params.monitor = new Monitor(); | 625 params.monitor = new Monitor(); |
| 643 | 626 |
| 644 { | 627 { |
| 645 MonitorLocker ml(params.monitor); | 628 MonitorLocker ml(params.monitor); |
| 646 EXPECT(params.spawned_thread_id == OSThread::kInvalidThreadId); | 629 EXPECT(params.spawned_thread_id == OSThread::kInvalidThreadId); |
| 647 // Spawn thread and wait to receive the thread id. | 630 // Spawn thread and wait to receive the thread id. |
| 648 OSThread::Start("ThreadIteratorTest", ThreadIteratorTestMain, | 631 OSThread::Start("ThreadIteratorTest", ThreadIteratorTestMain, |
| 649 reinterpret_cast<uword>(¶ms)); | 632 reinterpret_cast<uword>(¶ms)); |
| 650 while (params.spawned_thread_id == OSThread::kInvalidThreadId) { | 633 while (params.spawned_thread_id == OSThread::kInvalidThreadId) { |
| 651 ml.Wait(); | 634 ml.Wait(); |
| 652 } | 635 } |
| 653 EXPECT(params.spawned_thread_id != OSThread::kInvalidThreadId); | 636 EXPECT(params.spawned_thread_id != OSThread::kInvalidThreadId); |
| 654 EXPECT(params.spawned_thread_join_id != OSThread::kInvalidThreadJoinId); | 637 EXPECT(params.spawned_thread_join_id != OSThread::kInvalidThreadJoinId); |
| 655 OSThread::Join(params.spawned_thread_join_id); | 638 OSThread::Join(params.spawned_thread_join_id); |
| 656 } | 639 } |
| 657 | 640 |
| 658 EXPECT(!OSThread::IsThreadInList(params.spawned_thread_id)) | 641 EXPECT(!OSThread::IsThreadInList(params.spawned_thread_id)) |
| 659 | 642 |
| 660 delete params.monitor; | 643 delete params.monitor; |
| 661 } | 644 } |
| 662 | 645 |
| 663 | |
| 664 // Test rendezvous of: | 646 // Test rendezvous of: |
| 665 // - helpers in VM code, and | 647 // - helpers in VM code, and |
| 666 // - main thread in VM code, | 648 // - main thread in VM code, |
| 667 // organized by | 649 // organized by |
| 668 // - main thread, and | 650 // - main thread, and |
| 669 // - helpers. | 651 // - helpers. |
| 670 ISOLATE_UNIT_TEST_CASE(SafepointTestVM2) { | 652 ISOLATE_UNIT_TEST_CASE(SafepointTestVM2) { |
| 671 Isolate* isolate = thread->isolate(); | 653 Isolate* isolate = thread->isolate(); |
| 672 Monitor monitor; | 654 Monitor monitor; |
| 673 intptr_t expected_count = 0; | 655 intptr_t expected_count = 0; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 689 } while (!all_helpers); | 671 } while (!all_helpers); |
| 690 String& label = String::Handle(String::New("foo")); | 672 String& label = String::Handle(String::New("foo")); |
| 691 UserTag& tag = UserTag::Handle(UserTag::New(label)); | 673 UserTag& tag = UserTag::Handle(UserTag::New(label)); |
| 692 isolate->set_current_tag(tag); | 674 isolate->set_current_tag(tag); |
| 693 MonitorLocker ml(&monitor); | 675 MonitorLocker ml(&monitor); |
| 694 while (exited != SafepointTestTask::kTaskCount) { | 676 while (exited != SafepointTestTask::kTaskCount) { |
| 695 ml.WaitWithSafepointCheck(thread); | 677 ml.WaitWithSafepointCheck(thread); |
| 696 } | 678 } |
| 697 } | 679 } |
| 698 | 680 |
| 699 | |
| 700 // Test recursive safepoint operation scopes with other threads trying | 681 // Test recursive safepoint operation scopes with other threads trying |
| 701 // to also start a safepoint operation scope. | 682 // to also start a safepoint operation scope. |
| 702 ISOLATE_UNIT_TEST_CASE(RecursiveSafepointTest2) { | 683 ISOLATE_UNIT_TEST_CASE(RecursiveSafepointTest2) { |
| 703 Isolate* isolate = thread->isolate(); | 684 Isolate* isolate = thread->isolate(); |
| 704 Monitor monitor; | 685 Monitor monitor; |
| 705 intptr_t expected_count = 0; | 686 intptr_t expected_count = 0; |
| 706 intptr_t total_done = 0; | 687 intptr_t total_done = 0; |
| 707 intptr_t exited = 0; | 688 intptr_t exited = 0; |
| 708 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { | 689 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { |
| 709 Dart::thread_pool()->Run(new SafepointTestTask( | 690 Dart::thread_pool()->Run(new SafepointTestTask( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 729 { | 710 { |
| 730 SafepointOperationScope safepoint_scope(thread); | 711 SafepointOperationScope safepoint_scope(thread); |
| 731 MonitorLocker ml(&monitor); | 712 MonitorLocker ml(&monitor); |
| 732 if (exited == SafepointTestTask::kTaskCount) { | 713 if (exited == SafepointTestTask::kTaskCount) { |
| 733 all_exited = true; | 714 all_exited = true; |
| 734 } | 715 } |
| 735 } | 716 } |
| 736 } while (!all_exited); | 717 } while (!all_exited); |
| 737 } | 718 } |
| 738 | 719 |
| 739 | |
| 740 class AllocAndGCTask : public ThreadPool::Task { | 720 class AllocAndGCTask : public ThreadPool::Task { |
| 741 public: | 721 public: |
| 742 AllocAndGCTask(Isolate* isolate, Monitor* done_monitor, bool* done) | 722 AllocAndGCTask(Isolate* isolate, Monitor* done_monitor, bool* done) |
| 743 : isolate_(isolate), done_monitor_(done_monitor), done_(done) {} | 723 : isolate_(isolate), done_monitor_(done_monitor), done_(done) {} |
| 744 | 724 |
| 745 virtual void Run() { | 725 virtual void Run() { |
| 746 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); | 726 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); |
| 747 { | 727 { |
| 748 Thread* thread = Thread::Current(); | 728 Thread* thread = Thread::Current(); |
| 749 StackZone stack_zone(thread); | 729 StackZone stack_zone(thread); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 762 ml.Notify(); | 742 ml.Notify(); |
| 763 } | 743 } |
| 764 } | 744 } |
| 765 | 745 |
| 766 private: | 746 private: |
| 767 Isolate* isolate_; | 747 Isolate* isolate_; |
| 768 Monitor* done_monitor_; | 748 Monitor* done_monitor_; |
| 769 bool* done_; | 749 bool* done_; |
| 770 }; | 750 }; |
| 771 | 751 |
| 772 | |
| 773 ISOLATE_UNIT_TEST_CASE(HelperAllocAndGC) { | 752 ISOLATE_UNIT_TEST_CASE(HelperAllocAndGC) { |
| 774 Monitor done_monitor; | 753 Monitor done_monitor; |
| 775 bool done = false; | 754 bool done = false; |
| 776 Isolate* isolate = thread->isolate(); | 755 Isolate* isolate = thread->isolate(); |
| 777 Dart::thread_pool()->Run(new AllocAndGCTask(isolate, &done_monitor, &done)); | 756 Dart::thread_pool()->Run(new AllocAndGCTask(isolate, &done_monitor, &done)); |
| 778 { | 757 { |
| 779 while (true) { | 758 while (true) { |
| 780 TransitionVMToBlocked transition(thread); | 759 TransitionVMToBlocked transition(thread); |
| 781 MonitorLocker ml(&done_monitor); | 760 MonitorLocker ml(&done_monitor); |
| 782 if (done) { | 761 if (done) { |
| 783 break; | 762 break; |
| 784 } | 763 } |
| 785 } | 764 } |
| 786 } | 765 } |
| 787 } | 766 } |
| 788 | 767 |
| 789 } // namespace dart | 768 } // namespace dart |
| OLD | NEW |