| 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" | 8 #include "vm/unit_test.h" |
| 9 #include "vm/profiler.h" | 9 #include "vm/profiler.h" |
| 10 #include "vm/safepoint.h" |
| 11 #include "vm/stack_frame.h" |
| 10 #include "vm/thread_pool.h" | 12 #include "vm/thread_pool.h" |
| 11 #include "vm/thread_registry.h" | |
| 12 | 13 |
| 13 namespace dart { | 14 namespace dart { |
| 14 | 15 |
| 15 UNIT_TEST_CASE(Mutex) { | 16 UNIT_TEST_CASE(Mutex) { |
| 16 // This unit test case needs a running isolate. | 17 // This unit test case needs a running isolate. |
| 17 Dart_CreateIsolate( | 18 Dart_CreateIsolate( |
| 18 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); | 19 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); |
| 19 | 20 |
| 20 Mutex* mutex = new Mutex(); | 21 Mutex* mutex = new Mutex(); |
| 21 mutex->Lock(); | 22 mutex->Lock(); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 166 } |
| 166 | 167 |
| 167 private: | 168 private: |
| 168 Isolate* isolate_; | 169 Isolate* isolate_; |
| 169 Monitor* monitor_; | 170 Monitor* monitor_; |
| 170 bool* done_; | 171 bool* done_; |
| 171 intptr_t id_; | 172 intptr_t id_; |
| 172 }; | 173 }; |
| 173 | 174 |
| 174 | 175 |
| 175 TEST_CASE(ManyTasksWithZones) { | 176 VM_TEST_CASE(ManyTasksWithZones) { |
| 176 const int kTaskCount = 100; | 177 const int kTaskCount = 100; |
| 177 Monitor sync[kTaskCount]; | 178 Monitor sync[kTaskCount]; |
| 178 bool done[kTaskCount]; | 179 bool done[kTaskCount]; |
| 179 Isolate* isolate = Thread::Current()->isolate(); | 180 Isolate* isolate = Thread::Current()->isolate(); |
| 180 EXPECT(isolate->heap()->GrowthControlState()); | 181 EXPECT(isolate->heap()->GrowthControlState()); |
| 181 isolate->heap()->DisableGrowthControl(); | 182 isolate->heap()->DisableGrowthControl(); |
| 182 for (int i = 0; i < kTaskCount; i++) { | 183 for (int i = 0; i < kTaskCount; i++) { |
| 183 done[i] = false; | 184 done[i] = false; |
| 184 Dart::thread_pool()->Run( | 185 Dart::thread_pool()->Run( |
| 185 new TaskWithZoneAllocation(isolate, &sync[i], &done[i], i)); | 186 new TaskWithZoneAllocation(isolate, &sync[i], &done[i], i)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 201 } | 202 } |
| 202 EXPECT(bar.Equals("bar")); | 203 EXPECT(bar.Equals("bar")); |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 | 206 |
| 206 | 207 |
| 207 TEST_CASE(ThreadRegistry) { | 208 TEST_CASE(ThreadRegistry) { |
| 208 Isolate* orig = Thread::Current()->isolate(); | 209 Isolate* orig = Thread::Current()->isolate(); |
| 209 Zone* orig_zone = Thread::Current()->zone(); | 210 Zone* orig_zone = Thread::Current()->zone(); |
| 210 char* orig_str = orig_zone->PrintToString("foo"); | 211 char* orig_str = orig_zone->PrintToString("foo"); |
| 211 Thread::ExitIsolate(); | 212 Dart_ExitIsolate(); |
| 212 // Create and enter a new isolate. | 213 // Create and enter a new isolate. |
| 213 Dart_CreateIsolate( | 214 Dart_CreateIsolate( |
| 214 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); | 215 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); |
| 215 Zone* zone0 = Thread::Current()->zone(); | 216 Zone* zone0 = Thread::Current()->zone(); |
| 216 EXPECT(zone0 != orig_zone); | 217 EXPECT(zone0 != orig_zone); |
| 217 Dart_ShutdownIsolate(); | 218 Dart_ShutdownIsolate(); |
| 218 // Create and enter yet another isolate. | 219 // Create and enter yet another isolate. |
| 219 Dart_CreateIsolate( | 220 Dart_CreateIsolate( |
| 220 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); | 221 NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL); |
| 221 { | 222 { |
| 222 // Create a stack resource this time, and exercise it. | 223 // Create a stack resource this time, and exercise it. |
| 223 StackZone stack_zone(Thread::Current()); | 224 StackZone stack_zone(Thread::Current()); |
| 224 Zone* zone1 = Thread::Current()->zone(); | 225 Zone* zone1 = Thread::Current()->zone(); |
| 225 EXPECT(zone1 != zone0); | 226 EXPECT(zone1 != zone0); |
| 226 EXPECT(zone1 != orig_zone); | 227 EXPECT(zone1 != orig_zone); |
| 227 } | 228 } |
| 228 Dart_ShutdownIsolate(); | 229 Dart_ShutdownIsolate(); |
| 229 Thread::EnterIsolate(orig); | 230 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(orig)); |
| 230 // Original zone should be preserved. | 231 // Original zone should be preserved. |
| 231 EXPECT_EQ(orig_zone, Thread::Current()->zone()); | 232 EXPECT_EQ(orig_zone, Thread::Current()->zone()); |
| 232 EXPECT_STREQ("foo", orig_str); | 233 EXPECT_STREQ("foo", orig_str); |
| 233 } | 234 } |
| 234 | 235 |
| 235 | 236 |
| 236 // A helper thread that alternatingly cooperates and organizes | 237 // A helper thread that alternatingly cooperates and organizes |
| 237 // safepoint rendezvous. At rendezvous, it explicitly visits the | 238 // safepoint rendezvous. At rendezvous, it explicitly visits the |
| 238 // stacks looking for a specific marker (Smi) to verify that the expected | 239 // stacks looking for a specific marker (Smi) to verify that the expected |
| 239 // number threads are actually visited. The task is "done" when it has | 240 // number threads are actually visited. The task is "done" when it has |
| 240 // successfully made all other tasks and the main thread rendezvous (may | 241 // successfully made all other tasks and the main thread rendezvous (may |
| 241 // not happen in the first rendezvous, since tasks are still starting up). | 242 // not happen in the first rendezvous, since tasks are still starting up). |
| 242 class SafepointTestTask : public ThreadPool::Task { | 243 class SafepointTestTask : public ThreadPool::Task { |
| 243 public: | 244 public: |
| 244 static const intptr_t kTaskCount; | 245 static const intptr_t kTaskCount; |
| 245 | 246 |
| 246 SafepointTestTask(Isolate* isolate, | 247 SafepointTestTask(Isolate* isolate, |
| 247 Mutex* mutex, | 248 Monitor* monitor, |
| 248 intptr_t* expected_count, | 249 intptr_t* expected_count, |
| 249 intptr_t* total_done, | 250 intptr_t* total_done, |
| 250 intptr_t* exited) | 251 intptr_t* exited) |
| 251 : isolate_(isolate), | 252 : isolate_(isolate), |
| 252 mutex_(mutex), | 253 monitor_(monitor), |
| 253 expected_count_(expected_count), | 254 expected_count_(expected_count), |
| 254 total_done_(total_done), | 255 total_done_(total_done), |
| 255 exited_(exited), | 256 exited_(exited), |
| 256 local_done_(false) {} | 257 local_done_(false) {} |
| 257 | 258 |
| 258 virtual void Run() { | 259 virtual void Run() { |
| 259 Thread::EnterIsolateAsHelper(isolate_); | 260 Thread::EnterIsolateAsHelper(isolate_); |
| 260 { | 261 { |
| 261 MutexLocker ml(mutex_); | 262 MonitorLocker ml(monitor_); |
| 262 ++*expected_count_; | 263 ++*expected_count_; |
| 263 } | 264 } |
| 264 for (int i = 0; ; ++i) { | 265 Thread* thread = Thread::Current(); |
| 265 Thread* thread = Thread::Current(); | 266 for (int i = reinterpret_cast<intptr_t>(thread); ; ++i) { |
| 266 StackZone stack_zone(thread); | 267 StackZone stack_zone(thread); |
| 267 Zone* zone = thread->zone(); | 268 Zone* zone = thread->zone(); |
| 268 HANDLESCOPE(thread); | 269 HANDLESCOPE(thread); |
| 269 const intptr_t kUniqueSmi = 928327281; | 270 const intptr_t kUniqueSmi = 928327281; |
| 270 Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi)); | 271 Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi)); |
| 271 if ((i % 100) != 0) { | 272 if ((i % 100) != 0) { |
| 272 // Usually, we just cooperate. | 273 // Usually, we just cooperate. |
| 273 isolate_->thread_registry()->CheckSafepoint(); | 274 TransitionVMToBlocked transition(thread); |
| 274 } else { | 275 } else { |
| 275 // But occasionally, organize a rendezvous. | 276 // But occasionally, organize a rendezvous. |
| 276 isolate_->thread_registry()->SafepointThreads(); | 277 SafepointOperationScope safepoint_scope(thread); |
| 277 ObjectCounter counter(isolate_, &smi); | 278 ObjectCounter counter(isolate_, &smi); |
| 278 isolate_->IterateObjectPointers( | 279 isolate_->IterateObjectPointers( |
| 279 &counter, | 280 &counter, |
| 280 StackFrameIterator::kValidateFrames); | 281 StackFrameIterator::kValidateFrames); |
| 281 { | 282 { |
| 282 MutexLocker ml(mutex_); | 283 MonitorLocker ml(monitor_); |
| 283 EXPECT_EQ(*expected_count_, counter.count()); | 284 EXPECT_EQ(*expected_count_, counter.count()); |
| 284 } | 285 } |
| 285 UserTag& tag = UserTag::Handle(zone, isolate_->current_tag()); | 286 UserTag& tag = UserTag::Handle(zone, isolate_->current_tag()); |
| 286 if (tag.raw() != isolate_->default_tag()) { | 287 if (tag.raw() != isolate_->default_tag()) { |
| 287 String& label = String::Handle(zone, tag.label()); | 288 String& label = String::Handle(zone, tag.label()); |
| 288 EXPECT(label.Equals("foo")); | 289 EXPECT(label.Equals("foo")); |
| 289 MutexLocker ml(mutex_); | 290 MonitorLocker ml(monitor_); |
| 290 if (*expected_count_ == kTaskCount && !local_done_) { | 291 if (*expected_count_ == kTaskCount && !local_done_) { |
| 291 // Success for the first time! Remember that we are done, and | 292 // Success for the first time! Remember that we are done, and |
| 292 // update the total count. | 293 // update the total count. |
| 293 local_done_ = true; | 294 local_done_ = true; |
| 294 ++*total_done_; | 295 ++*total_done_; |
| 295 } | 296 } |
| 296 } | 297 } |
| 297 isolate_->thread_registry()->ResumeAllThreads(); | |
| 298 } | 298 } |
| 299 // Check whether everyone is done. | 299 // Check whether everyone is done. |
| 300 { | 300 { |
| 301 MutexLocker ml(mutex_); | 301 MonitorLocker ml(monitor_); |
| 302 if (*total_done_ == kTaskCount) { | 302 if (*total_done_ == kTaskCount) { |
| 303 // Another task might be at SafepointThreads when resuming. Ensure its | 303 // Another task might be at SafepointThreads when resuming. Ensure its |
| 304 // expectation reflects reality, since we pop our handles here. | 304 // expectation reflects reality, since we pop our handles here. |
| 305 --*expected_count_; | 305 --*expected_count_; |
| 306 break; | 306 break; |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 } | 309 } |
| 310 Thread::ExitIsolateAsHelper(); | 310 Thread::ExitIsolateAsHelper(); |
| 311 { | 311 { |
| 312 MutexLocker ml(mutex_); | 312 MonitorLocker ml(monitor_); |
| 313 ++*exited_; | 313 ++*exited_; |
| 314 ml.Notify(); |
| 314 } | 315 } |
| 315 } | 316 } |
| 316 | 317 |
| 317 private: | 318 private: |
| 318 Isolate* isolate_; | 319 Isolate* isolate_; |
| 319 Mutex* mutex_; | 320 Monitor* monitor_; |
| 320 intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit. | 321 intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit. |
| 321 intptr_t* total_done_; // # tasks that successfully safepointed once. | 322 intptr_t* total_done_; // # tasks that successfully safepointed once. |
| 322 intptr_t* exited_; // # tasks that are no longer running. | 323 intptr_t* exited_; // # tasks that are no longer running. |
| 323 bool local_done_; // this task has successfully safepointed >= once. | 324 bool local_done_; // this task has successfully safepointed >= once. |
| 324 }; | 325 }; |
| 325 | 326 |
| 326 | 327 |
| 327 const intptr_t SafepointTestTask::kTaskCount = 5; | 328 const intptr_t SafepointTestTask::kTaskCount = 5; |
| 328 | 329 |
| 329 | 330 |
| 330 // Test rendezvous of: | 331 // Test rendezvous of: |
| 331 // - helpers in VM code, | 332 // - helpers in VM code, |
| 332 // - main thread in pure Dart, | 333 // - main thread in pure Dart, |
| 333 // organized by | 334 // organized by |
| 334 // - helpers. | 335 // - helpers. |
| 335 TEST_CASE(SafepointTestDart) { | 336 TEST_CASE(SafepointTestDart) { |
| 336 Isolate* isolate = Thread::Current()->isolate(); | 337 Isolate* isolate = Thread::Current()->isolate(); |
| 337 Mutex mutex; | 338 Monitor monitor; |
| 338 intptr_t expected_count = 0; | 339 intptr_t expected_count = 0; |
| 339 intptr_t total_done = 0; | 340 intptr_t total_done = 0; |
| 340 intptr_t exited = 0; | 341 intptr_t exited = 0; |
| 341 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { | 342 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { |
| 342 Dart::thread_pool()->Run(new SafepointTestTask( | 343 Dart::thread_pool()->Run(new SafepointTestTask( |
| 343 isolate, &mutex, &expected_count, &total_done, &exited)); | 344 isolate, &monitor, &expected_count, &total_done, &exited)); |
| 344 } | 345 } |
| 345 // Run Dart code on the main thread long enough to allow all helpers | 346 // Run Dart code on the main thread long enough to allow all helpers |
| 346 // to get their verification done and exit. Use a specific UserTag | 347 // to get their verification done and exit. Use a specific UserTag |
| 347 // to enable the helpers to verify that the main thread is | 348 // to enable the helpers to verify that the main thread is |
| 348 // successfully interrupted in the pure Dart loop. | 349 // successfully interrupted in the pure Dart loop. |
| 349 #if defined(USING_SIMULATOR) | 350 #if defined(USING_SIMULATOR) |
| 350 const intptr_t kLoopCount = 12345678; | 351 const intptr_t kLoopCount = 12345678; |
| 351 #else | 352 #else |
| 352 const intptr_t kLoopCount = 1234567890; | 353 const intptr_t kLoopCount = 1234567890; |
| 353 #endif // USING_SIMULATOR | 354 #endif // USING_SIMULATOR |
| 354 char buffer[1024]; | 355 char buffer[1024]; |
| 355 OS::SNPrint(buffer, sizeof(buffer), | 356 OS::SNPrint(buffer, sizeof(buffer), |
| 356 "import 'dart:developer';\n" | 357 "import 'dart:developer';\n" |
| 357 "int dummy = 0;\n" | 358 "int dummy = 0;\n" |
| 358 "main() {\n" | 359 "main() {\n" |
| 359 " new UserTag('foo').makeCurrent();\n" | 360 " new UserTag('foo').makeCurrent();\n" |
| 360 " for (dummy = 0; dummy < %" Pd "; ++dummy) {\n" | 361 " for (dummy = 0; dummy < %" Pd "; ++dummy) {\n" |
| 361 " dummy += (dummy & 1);\n" | 362 " dummy += (dummy & 1);\n" |
| 362 " }\n" | 363 " }\n" |
| 363 "}\n", kLoopCount); | 364 "}\n", kLoopCount); |
| 364 Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL); | 365 Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL); |
| 365 EXPECT_VALID(lib); | 366 EXPECT_VALID(lib); |
| 366 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 367 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 367 EXPECT_VALID(result); | 368 EXPECT_VALID(result); |
| 368 // Ensure we looped long enough to allow all helpers to succeed and exit. | 369 // Ensure we looped long enough to allow all helpers to succeed and exit. |
| 369 { | 370 { |
| 370 MutexLocker ml(&mutex); | 371 MonitorLocker ml(&monitor); |
| 372 while (exited != SafepointTestTask::kTaskCount) { |
| 373 ml.Wait(); |
| 374 } |
| 371 EXPECT_EQ(SafepointTestTask::kTaskCount, total_done); | 375 EXPECT_EQ(SafepointTestTask::kTaskCount, total_done); |
| 372 EXPECT_EQ(SafepointTestTask::kTaskCount, exited); | 376 EXPECT_EQ(SafepointTestTask::kTaskCount, exited); |
| 373 } | 377 } |
| 374 } | 378 } |
| 375 | 379 |
| 376 | 380 |
| 377 // Test rendezvous of: | 381 // Test rendezvous of: |
| 378 // - helpers in VM code, and | 382 // - helpers in VM code, and |
| 379 // - main thread in VM code, | 383 // - main thread in VM code, |
| 380 // organized by | 384 // organized by |
| 381 // - helpers. | 385 // - helpers. |
| 382 TEST_CASE(SafepointTestVM) { | 386 VM_TEST_CASE(SafepointTestVM) { |
| 383 Isolate* isolate = thread->isolate(); | 387 Isolate* isolate = thread->isolate(); |
| 384 Mutex mutex; | 388 Monitor monitor; |
| 385 intptr_t expected_count = 0; | 389 intptr_t expected_count = 0; |
| 386 intptr_t total_done = 0; | 390 intptr_t total_done = 0; |
| 387 intptr_t exited = 0; | 391 intptr_t exited = 0; |
| 388 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { | 392 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { |
| 389 Dart::thread_pool()->Run(new SafepointTestTask( | 393 Dart::thread_pool()->Run(new SafepointTestTask( |
| 390 isolate, &mutex, &expected_count, &total_done, &exited)); | 394 isolate, &monitor, &expected_count, &total_done, &exited)); |
| 391 } | 395 } |
| 392 String& label = String::Handle(String::New("foo")); | 396 String& label = String::Handle(String::New("foo")); |
| 393 UserTag& tag = UserTag::Handle(UserTag::New(label)); | 397 UserTag& tag = UserTag::Handle(UserTag::New(label)); |
| 394 isolate->set_current_tag(tag); | 398 isolate->set_current_tag(tag); |
| 395 while (true) { | 399 MonitorLocker ml(&monitor); |
| 396 isolate->thread_registry()->CheckSafepoint(); | 400 while (exited != SafepointTestTask::kTaskCount) { |
| 397 MutexLocker ml(&mutex); | 401 ml.WaitWithSafepointCheck(thread); |
| 398 if (exited == SafepointTestTask::kTaskCount) { | |
| 399 break; | |
| 400 } | |
| 401 } | 402 } |
| 402 } | 403 } |
| 403 | 404 |
| 404 | 405 |
| 405 TEST_CASE(ThreadIterator_Count) { | 406 VM_TEST_CASE(ThreadIterator_Count) { |
| 406 intptr_t thread_count_0 = 0; | 407 intptr_t thread_count_0 = 0; |
| 407 intptr_t thread_count_1 = 0; | 408 intptr_t thread_count_1 = 0; |
| 408 | 409 |
| 409 { | 410 { |
| 410 OSThreadIterator ti; | 411 OSThreadIterator ti; |
| 411 while (ti.HasNext()) { | 412 while (ti.HasNext()) { |
| 412 OSThread* thread = ti.Next(); | 413 OSThread* thread = ti.Next(); |
| 413 EXPECT(thread != NULL); | 414 EXPECT(thread != NULL); |
| 414 thread_count_0++; | 415 thread_count_0++; |
| 415 } | 416 } |
| 416 } | 417 } |
| 417 | 418 |
| 418 { | 419 { |
| 419 OSThreadIterator ti; | 420 OSThreadIterator ti; |
| 420 while (ti.HasNext()) { | 421 while (ti.HasNext()) { |
| 421 OSThread* thread = ti.Next(); | 422 OSThread* thread = ti.Next(); |
| 422 EXPECT(thread != NULL); | 423 EXPECT(thread != NULL); |
| 423 thread_count_1++; | 424 thread_count_1++; |
| 424 } | 425 } |
| 425 } | 426 } |
| 426 | 427 |
| 427 EXPECT(thread_count_0 > 0); | 428 EXPECT(thread_count_0 > 0); |
| 428 EXPECT(thread_count_1 > 0); | 429 EXPECT(thread_count_1 > 0); |
| 429 EXPECT(thread_count_0 >= thread_count_1); | 430 EXPECT(thread_count_0 >= thread_count_1); |
| 430 } | 431 } |
| 431 | 432 |
| 432 | 433 |
| 433 TEST_CASE(ThreadIterator_FindSelf) { | 434 VM_TEST_CASE(ThreadIterator_FindSelf) { |
| 434 OSThread* current = OSThread::Current(); | 435 OSThread* current = OSThread::Current(); |
| 435 EXPECT(OSThread::IsThreadInList(current->join_id())); | 436 EXPECT(OSThread::IsThreadInList(current->join_id())); |
| 436 } | 437 } |
| 437 | 438 |
| 438 | 439 |
| 439 struct ThreadIteratorTestParams { | 440 struct ThreadIteratorTestParams { |
| 440 ThreadId spawned_thread_join_id; | 441 ThreadId spawned_thread_join_id; |
| 441 Monitor* monitor; | 442 Monitor* monitor; |
| 442 }; | 443 }; |
| 443 | 444 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 delete params.monitor; | 484 delete params.monitor; |
| 484 } | 485 } |
| 485 | 486 |
| 486 | 487 |
| 487 // Test rendezvous of: | 488 // Test rendezvous of: |
| 488 // - helpers in VM code, and | 489 // - helpers in VM code, and |
| 489 // - main thread in VM code, | 490 // - main thread in VM code, |
| 490 // organized by | 491 // organized by |
| 491 // - main thread, and | 492 // - main thread, and |
| 492 // - helpers. | 493 // - helpers. |
| 493 TEST_CASE(SafepointTestVM2) { | 494 VM_TEST_CASE(SafepointTestVM2) { |
| 494 Isolate* isolate = thread->isolate(); | 495 Isolate* isolate = thread->isolate(); |
| 495 Mutex mutex; | 496 Monitor monitor; |
| 496 intptr_t expected_count = 0; | 497 intptr_t expected_count = 0; |
| 497 intptr_t total_done = 0; | 498 intptr_t total_done = 0; |
| 498 intptr_t exited = 0; | 499 intptr_t exited = 0; |
| 499 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { | 500 for (int i = 0; i < SafepointTestTask::kTaskCount; i++) { |
| 500 Dart::thread_pool()->Run(new SafepointTestTask( | 501 Dart::thread_pool()->Run(new SafepointTestTask( |
| 501 isolate, &mutex, &expected_count, &total_done, &exited)); | 502 isolate, &monitor, &expected_count, &total_done, &exited)); |
| 502 } | 503 } |
| 503 bool all_helpers = false; | 504 bool all_helpers = false; |
| 504 do { | 505 do { |
| 505 isolate->thread_registry()->SafepointThreads(); | 506 SafepointOperationScope safepoint_scope(thread); |
| 506 { | 507 { |
| 507 MutexLocker ml(&mutex); | 508 MonitorLocker ml(&monitor); |
| 508 if (expected_count == SafepointTestTask::kTaskCount) { | 509 if (expected_count == SafepointTestTask::kTaskCount) { |
| 509 all_helpers = true; | 510 all_helpers = true; |
| 510 } | 511 } |
| 511 } | 512 } |
| 512 isolate->thread_registry()->ResumeAllThreads(); | |
| 513 } while (!all_helpers); | 513 } while (!all_helpers); |
| 514 String& label = String::Handle(String::New("foo")); | 514 String& label = String::Handle(String::New("foo")); |
| 515 UserTag& tag = UserTag::Handle(UserTag::New(label)); | 515 UserTag& tag = UserTag::Handle(UserTag::New(label)); |
| 516 isolate->set_current_tag(tag); | 516 isolate->set_current_tag(tag); |
| 517 while (true) { | 517 MonitorLocker ml(&monitor); |
| 518 isolate->thread_registry()->CheckSafepoint(); | 518 while (exited != SafepointTestTask::kTaskCount) { |
| 519 MutexLocker ml(&mutex); | 519 ml.WaitWithSafepointCheck(thread); |
| 520 if (exited == SafepointTestTask::kTaskCount) { | |
| 521 break; | |
| 522 } | |
| 523 } | 520 } |
| 524 } | 521 } |
| 525 | 522 |
| 526 | 523 |
| 527 class AllocAndGCTask : public ThreadPool::Task { | 524 class AllocAndGCTask : public ThreadPool::Task { |
| 528 public: | 525 public: |
| 529 AllocAndGCTask(Isolate* isolate, | 526 AllocAndGCTask(Isolate* isolate, |
| 530 Monitor* done_monitor, | 527 Monitor* done_monitor, |
| 531 bool* done) | 528 bool* done) |
| 532 : isolate_(isolate), | 529 : isolate_(isolate), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 555 } | 552 } |
| 556 } | 553 } |
| 557 | 554 |
| 558 private: | 555 private: |
| 559 Isolate* isolate_; | 556 Isolate* isolate_; |
| 560 Monitor* done_monitor_; | 557 Monitor* done_monitor_; |
| 561 bool* done_; | 558 bool* done_; |
| 562 }; | 559 }; |
| 563 | 560 |
| 564 | 561 |
| 565 TEST_CASE(HelperAllocAndGC) { | 562 VM_TEST_CASE(HelperAllocAndGC) { |
| 566 Monitor done_monitor; | 563 Monitor done_monitor; |
| 567 bool done = false; | 564 bool done = false; |
| 568 Isolate* isolate = Thread::Current()->isolate(); | 565 Isolate* isolate = thread->isolate(); |
| 569 Dart::thread_pool()->Run(new AllocAndGCTask(isolate, &done_monitor, &done)); | 566 Dart::thread_pool()->Run(new AllocAndGCTask(isolate, &done_monitor, &done)); |
| 570 { | 567 { |
| 571 while (true) { | 568 while (true) { |
| 572 isolate->thread_registry()->CheckSafepoint(); | 569 TransitionVMToBlocked transition(thread); |
| 573 MonitorLocker ml(&done_monitor); | 570 MonitorLocker ml(&done_monitor); |
| 574 if (done) { | 571 if (done) { |
| 575 break; | 572 break; |
| 576 } | 573 } |
| 577 } | 574 } |
| 578 } | 575 } |
| 579 } | 576 } |
| 580 | 577 |
| 581 } // namespace dart | 578 } // namespace dart |
| OLD | NEW |