Chromium Code Reviews| Index: runtime/vm/thread_test.cc |
| diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc |
| index 2dcf56805513f9745f792203630750b50a37fe09..0f07f53543a815165faa73fb960fe29665cad673 100644 |
| --- a/runtime/vm/thread_test.cc |
| +++ b/runtime/vm/thread_test.cc |
| @@ -205,6 +205,173 @@ VM_TEST_CASE(ManyTasksWithZones) { |
| } |
| +#if defined(DEBUG) |
|
zra
2016/12/08 18:54:13
ditto
bkonyi
2016/12/08 20:58:32
Done.
|
| +class SimpleTaskWithZoneAllocation : public ThreadPool::Task { |
| + public: |
| + SimpleTaskWithZoneAllocation(intptr_t id, |
| + Isolate* isolate, |
| + Thread** thread_ptr, |
| + Monitor* sync, |
| + Monitor* monitor, |
| + intptr_t* done_count, |
| + bool* wait) |
| + : id_(id), |
| + isolate_(isolate), |
| + thread_ptr_(thread_ptr), |
| + sync_(sync), |
| + monitor_(monitor), |
| + done_count_(done_count), |
| + wait_(wait) {} |
| + |
| + virtual void Run() { |
| + Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); |
| + { |
| + Thread* thread = Thread::Current(); |
| + *thread_ptr_ = thread; |
| + CreateStackZones(id_); |
| + } |
| + Thread::ExitIsolateAsHelper(); |
| + // Notify the main thread that this thread has exited. |
| + { |
| + MonitorLocker ml(monitor_); |
| + *done_count_ += 1; |
| + ml.Notify(); |
| + } |
| + } |
| + |
| + private: |
| + void CreateStackZones(intptr_t num) { |
| + Thread* thread = Thread::Current(); |
| + *thread_ptr_ = thread; |
| + |
| + StackZone stack_zone(thread); |
| + HANDLESCOPE(thread); |
| + Zone* zone = thread->zone(); |
| + EXPECT_EQ(zone, stack_zone.GetZone()); |
| + |
| + // Create a zone (which is also a stack resource) and exercise it a bit. |
| + ZoneGrowableArray<bool>* a0 = new (zone) ZoneGrowableArray<bool>(zone, 1); |
| + GrowableArray<bool> a1(zone, 1); |
| + for (intptr_t i = 0; i < 1000 * num + id_; ++i) { |
| + a0->Add(true); |
| + a1.Add(true); |
| + } |
| + |
| + num -= 1; |
| + if (num != 0) { |
| + CreateStackZones(num); |
| + return; |
| + } |
| + { |
| + // Let the main thread know we're done with memory ops on this thread. |
| + MonitorLocker ml(monitor_); |
| + *done_count_ += 1; |
| + ml.Notify(); |
| + } |
| + // Wait for the go-ahead from the main thread to exit. |
| + { |
| + MonitorLocker sync_ml(sync_); |
| + while (*wait_) { |
| + sync_ml.Wait(); |
| + } |
| + } |
| + } |
|
zra
2016/12/08 18:54:13
missing newline.
bkonyi
2016/12/08 20:58:32
Done.
|
| + intptr_t id_; |
| + Isolate* isolate_; |
| + Thread** thread_ptr_; |
| + Monitor* sync_; |
| + Monitor* monitor_; |
| + intptr_t* done_count_; |
| + bool* wait_; |
| +}; |
| + |
| + |
| +TEST_CASE(ManySimpleTasksWithZones) { |
| + const int kTaskCount = 10; |
| + Monitor monitor; |
| + Monitor sync; |
| + Thread* threads[kTaskCount + 1]; |
| + Isolate* isolate = Thread::Current()->isolate(); |
| + intptr_t done_count = 0; |
| + bool wait = true; |
| + threads[kTaskCount] = Thread::Current(); |
| + |
| + EXPECT(isolate->heap()->GrowthControlState()); |
| + isolate->heap()->DisableGrowthControl(); |
| + for (int i = 0; i < kTaskCount; i++) { |
|
zra
2016/12/08 18:54:13
intptr_t i
bkonyi
2016/12/08 20:58:32
Done.
|
| + Dart::thread_pool()->Run(new SimpleTaskWithZoneAllocation( |
| + (i + 1), isolate, &threads[i], &sync, &monitor, &done_count, &wait)); |
| + } |
| + // Wait until all spawned tasks finish their memory operations. |
| + { |
| + MonitorLocker ml(&monitor); |
| + while (done_count < kTaskCount) { |
| + ml.Wait(); |
| + } |
| + // Reset the done counter for use later. |
| + done_count = 0; |
| + } |
| + |
| + JSONStream stream; |
| + Service::PrintJSONForVM(&stream, false); |
| + const char* json = stream.ToCString(); |
| + |
| + // Confirm all expected entries are in the JSON output. |
| + for (int i = 0; i < kTaskCount + 1; i++) { |
|
zra
2016/12/08 18:54:13
intptr_t i
bkonyi
2016/12/08 20:58:32
Done.
|
| + Thread* thread = threads[i]; |
| + Isolate* thread_isolate = thread->isolate(); |
| + // Buffer can handle any possible input length given types. |
| + char thread_address_buf[96]; |
| + char isolate_address_buf[64]; |
| + Zone* top_zone = thread->zone(); |
| + |
| + // Check that all zones are present with correct sizes. |
| + while (top_zone != NULL) { |
| + char zone_info_buf[96]; |
| + OS::SNPrint(zone_info_buf, sizeof(zone_info_buf), |
| + "\"type\":\"_Zone\"," |
| + "\"capacity\":%ld," |
| + "\"used\":%ld", |
| + top_zone->SizeInBytes(), top_zone->UsedSizeInBytes()); |
| + |
| + EXPECT_SUBSTRING(zone_info_buf, json); |
| + top_zone = top_zone->previous(); |
| + } |
| + |
| + // Check the thread exists and is the correct size. |
| + OS::SNPrint(thread_address_buf, sizeof(thread_address_buf), |
| + "\"type\":\"_Thread\"," |
| + "\"id\":\"threads\\/%" Pd64 "", |
| + thread->os_thread()->trace_id()); |
| + |
| + // Ensure the isolate for each thread is valid. |
| + OS::SNPrint(isolate_address_buf, sizeof(isolate_address_buf), |
| + "\"type\":\"Isolate\"," |
| + "\"fixedId\":true," |
| + "\"id\":\"isolates\\/%" Pd64 "", |
| + static_cast<int64_t>(thread_isolate->main_port())); |
| + |
| + EXPECT_SUBSTRING(thread_address_buf, json); |
| + EXPECT_SUBSTRING(isolate_address_buf, json); |
| + } |
| + |
| + // Unblock the tasks so they can finish. |
| + { |
| + MonitorLocker sync_ml(&sync); |
| + wait = false; |
| + sync_ml.NotifyAll(); |
| + } |
| + // Now wait for them all to exit before destroying the isolate. |
| + { |
| + MonitorLocker ml(&monitor); |
| + while (done_count < kTaskCount) { |
| + ml.Wait(); |
| + } |
| + } |
| +} |
| +#endif |
| + |
| + |
| TEST_CASE(ThreadRegistry) { |
| Isolate* orig = Thread::Current()->isolate(); |
| Zone* orig_zone = Thread::Current()->zone(); |