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

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: Ready for review. 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
Index: runtime/vm/thread_test.cc
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index f781783d8e43dd403a088228bc4248e126446c3d..1d81b9b052755ac55e822d66c61bbaf042a3e25e 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -224,4 +224,202 @@ 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 = 5;
+
+ SafepointTestTask(Isolate* isolate,
+ Mutex* mutex,
+ intptr_t* expected_count,
+ intptr_t* done,
+ intptr_t* exited)
+ : isolate_(isolate),
+ mutex_(mutex),
+ expected_count_(expected_count),
+ done_(done),
+ exited_(exited) {}
+
+ virtual void Run() {
+ Thread::EnterIsolateAsHelper(isolate_);
+ for (int i = 0; ; ++i) {
+ Thread* thread = Thread::Current();
+ StackZone stack_zone(thread);
+ Zone* zone = thread->zone();
+ HANDLESCOPE(thread);
+ const intptr_t kUniqueSmi = 928327281;
+ Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi));
+ {
+ MutexLocker ml(mutex_);
+ ++*expected_count_;
+ }
+ if ((i % 100) != 0) {
+ // Usually, we just cooperate.
+ isolate_->thread_registry()->CheckSafepoint();
+ } else {
+ // But occasionally, organize a rendezvous.
+ isolate_->thread_registry()->SafepointAllThreads();
+ 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"));
+ MutexLocker ml(mutex_);
+ if (*expected_count_ == kTaskCount) {
+ ++*done_;
+ }
+ }
+ isolate_->thread_registry()->ResumeAllThreads();
+ }
+ // Clear handle and adjust expectation. Check whether we're done.
+ smi = Smi::New(0);
+ {
+ MutexLocker ml(mutex_);
+ --*expected_count_;
+ if (*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* done_; // # tasks that successfully safepointed once.
+ intptr_t* exited_; // # tasks that are no longer running.
+};
+
+
+// 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 done = 0;
+ intptr_t exited = 0;
+ const intptr_t num_tasks = SafepointTestTask::kTaskCount; // Please compiler.
Ivan Posva 2015/07/31 20:28:09 Comment does not parse.
koda 2015/07/31 22:40:44 Linker was unhappy with the inlined static constan
+ for (int i = 0; i < num_tasks; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &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.
+ 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 < 1234567890; ++dummy) {\n"
Ivan Posva 2015/07/31 20:28:09 How long does this test execute on simulated archi
koda 2015/07/31 22:40:44 Now using smaller loop count if USING_SIMULATOR.
+ " dummy += (dummy & 1);\n"
+ " }\n"
+ "}\n");
+ 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(num_tasks, done);
+ EXPECT_EQ(num_tasks, 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 done = 0;
+ intptr_t exited = 0;
+ const intptr_t num_tasks = SafepointTestTask::kTaskCount; // Please compiler.
+ for (int i = 0; i < num_tasks; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &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 == num_tasks) {
+ 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 done = 0;
+ intptr_t exited = 0;
+ const intptr_t num_tasks = SafepointTestTask::kTaskCount; // Please compiler.
+ for (int i = 0; i < num_tasks; i++) {
+ Dart::thread_pool()->Run(new SafepointTestTask(
+ isolate, &mutex, &expected_count, &done, &exited));
+ }
+ bool all_helpers = false;
+ do {
+ isolate->thread_registry()->SafepointAllThreads();
+ {
+ MutexLocker ml(&mutex);
+ if (expected_count == num_tasks) {
+ 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 == num_tasks) {
+ break;
+ }
+ }
+}
+
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698