Chromium Code Reviews| 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/thread_pool.h" | 10 #include "vm/thread_pool.h" |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 |
| OLD | NEW |