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

Unified 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, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/thread_registry.cc ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/thread_test.cc
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index f781783d8e43dd403a088228bc4248e126446c3d..4ef917f303d84b2264e7d714c9d331267867c40f 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -224,4 +224,211 @@ TEST_CASE(ThreadRegistry) {
delete isos[1];
}
+
+// A helper thread that alternatingly cooperates and organizes
+// safepoint rendezvous. At rendezvous, it explicitly visits the
+// stacks looking for a specific marker (Smi) to verify that the expected
+// number threads are actually visited. The task is "done" when it has
+// successfully made all other tasks and the main thread rendezvous (may
+// not happen in the first rendezvous, since tasks are still starting up).
+class SafepointTestTask : public ThreadPool::Task {
+ public:
+ static const intptr_t kTaskCount;
+
+ SafepointTestTask(Isolate* isolate,
+ Mutex* mutex,
+ intptr_t* expected_count,
+ intptr_t* total_done,
+ intptr_t* exited)
+ : isolate_(isolate),
+ mutex_(mutex),
+ expected_count_(expected_count),
+ total_done_(total_done),
+ exited_(exited),
+ local_done_(false) {}
+
+ virtual void Run() {
+ Thread::EnterIsolateAsHelper(isolate_);
+ {
+ MutexLocker ml(mutex_);
+ ++*expected_count_;
+ }
+ for (int i = 0; ; ++i) {
+ Thread* thread = Thread::Current();
+ StackZone stack_zone(thread);
+ 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.
+ HANDLESCOPE(thread);
+ const intptr_t kUniqueSmi = 928327281;
+ Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi));
+ if ((i % 100) != 0) {
+ // Usually, we just cooperate.
+ isolate_->thread_registry()->CheckSafepoint();
+ } else {
+ // But occasionally, organize a rendezvous.
+ isolate_->thread_registry()->SafepointThreads();
+ ObjectCounter counter(isolate_, &smi);
+ isolate_->thread_registry()->VisitObjectPointers(&counter);
+ {
+ MutexLocker ml(mutex_);
+ EXPECT_EQ(*expected_count_, counter.count());
+ }
+ UserTag& tag = UserTag::Handle(zone, isolate_->current_tag());
+ if (tag.raw() != isolate_->default_tag()) {
+ String& label = String::Handle(zone, tag.label());
+ EXPECT(label.Equals("foo"));
+ // if this is the first time.
+ MutexLocker ml(mutex_);
+ if (*expected_count_ == kTaskCount && !local_done_) {
+ // Success for the first time! Remember that we are done, and
+ // update the total count.
+ local_done_ = true;
+ ++*total_done_;
+ }
+ }
+ isolate_->thread_registry()->ResumeAllThreads();
+ }
+ // Check whether everyone is done.
+ {
+ MutexLocker ml(mutex_);
+ if (*total_done_ == kTaskCount) {
+ break;
+ }
+ }
+ }
+ Thread::ExitIsolateAsHelper();
+ {
+ MutexLocker ml(mutex_);
+ ++*exited_;
+ }
+ }
+
+ private:
+ Isolate* isolate_;
+ Mutex* mutex_;
+ intptr_t* expected_count_; // # copies of kUniqueSmi we expect to visit.
+ intptr_t* total_done_; // # tasks that successfully safepointed once.
+ intptr_t* exited_; // # tasks that are no longer running.
+ bool local_done_; // this task has successfully safepointed >= once.
+};
+
+
+const intptr_t SafepointTestTask::kTaskCount = 5;
+
+
+// Test rendezvous of:
+// - helpers in VM code,
+// - main thread in pure Dart,
+// organized by
+// - helpers.
+TEST_CASE(SafepointTestDart) {
+ Isolate* isolate = Thread::Current()->isolate();
+ Mutex mutex;
+ intptr_t expected_count = 0;
+ intptr_t total_done = 0;
+ intptr_t exited = 0;
+ for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &total_done, &exited));
+ }
+ // Run Dart code on the main thread long enough to allow all helpers
+ // to get their verification done and exit. Use a specific UserTag
+ // to enable the helpers to verify that the main thread is
+ // successfully interrupted in the pure Dart loop.
+#if defined(USING_SIMULATOR)
+ const intptr_t kLoopCount = 12345678;
+#else
+ const intptr_t kLoopCount = 1234567890;
+#endif // USING_SIMULATOR
+ char buffer[1024];
+ OS::SNPrint(buffer, sizeof(buffer),
+ "import 'dart:profiler';\n"
+ "int dummy = 0;\n"
+ "main() {\n"
+ " new UserTag('foo').makeCurrent();\n"
+ " for (dummy = 0; dummy < %" Pd "; ++dummy) {\n"
+ " dummy += (dummy & 1);\n"
+ " }\n"
+ "}\n", kLoopCount);
+ Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
+ EXPECT_VALID(lib);
+ Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+ EXPECT_VALID(result);
+ // Ensure we looped long enough to allow all helpers to succeed and exit.
+ {
+ MutexLocker ml(&mutex);
+ EXPECT_EQ(SafepointTestTask::kTaskCount, total_done);
+ EXPECT_EQ(SafepointTestTask::kTaskCount, exited);
+ }
+}
+
+
+// Test rendezvous of:
+// - helpers in VM code, and
+// - main thread in VM code,
+// organized by
+// - helpers.
+TEST_CASE(SafepointTestVM) {
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
+ Mutex mutex;
+ intptr_t expected_count = 0;
+ intptr_t total_done = 0;
+ intptr_t exited = 0;
+ for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &total_done, &exited));
+ }
+ String& label = String::Handle(String::New("foo"));
+ UserTag& tag = UserTag::Handle(UserTag::New(label));
+ isolate->set_current_tag(tag);
+ while (true) {
+ isolate->thread_registry()->CheckSafepoint();
+ MutexLocker ml(&mutex);
+ if (exited == SafepointTestTask::kTaskCount) {
+ break;
+ }
+ }
+}
+
+
+// Test rendezvous of:
+// - helpers in VM code, and
+// - main thread in VM code,
+// organized by
+// - main thread, and
+// - helpers.
+TEST_CASE(SafepointTestVM2) {
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
+ Mutex mutex;
+ intptr_t expected_count = 0;
+ intptr_t total_done = 0;
+ intptr_t exited = 0;
+ for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &total_done, &exited));
+ }
+ bool all_helpers = false;
+ do {
+ isolate->thread_registry()->SafepointThreads();
+ {
+ MutexLocker ml(&mutex);
+ if (expected_count == SafepointTestTask::kTaskCount) {
+ all_helpers = true;
+ }
+ }
+ isolate->thread_registry()->ResumeAllThreads();
+ } while (!all_helpers);
+ String& label = String::Handle(String::New("foo"));
+ UserTag& tag = UserTag::Handle(UserTag::New(label));
+ isolate->set_current_tag(tag);
+ while (true) {
+ isolate->thread_registry()->CheckSafepoint();
+ MutexLocker ml(&mutex);
+ if (exited == SafepointTestTask::kTaskCount) {
+ break;
+ }
+ }
+}
+
} // namespace dart
« 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