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/safepoint.h" | 10 #include "vm/safepoint.h" |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 } | 198 } |
| 199 EXPECT(done[i]); | 199 EXPECT(done[i]); |
| 200 if (i % 10 == 0) { | 200 if (i % 10 == 0) { |
| 201 Thread::EnterIsolate(isolate); | 201 Thread::EnterIsolate(isolate); |
| 202 } | 202 } |
| 203 EXPECT(bar.Equals("bar")); | 203 EXPECT(bar.Equals("bar")); |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 | 206 |
| 207 | 207 |
| 208 #ifndef PRODUCT | |
| 209 class SimpleTaskWithZoneAllocation : public ThreadPool::Task { | |
| 210 public: | |
| 211 SimpleTaskWithZoneAllocation(intptr_t id, | |
| 212 Isolate* isolate, | |
| 213 Thread** thread_ptr, | |
| 214 Monitor* sync, | |
| 215 Monitor* monitor, | |
| 216 intptr_t* done_count, | |
| 217 bool* wait) | |
| 218 : id_(id), | |
| 219 isolate_(isolate), | |
| 220 thread_ptr_(thread_ptr), | |
| 221 sync_(sync), | |
| 222 monitor_(monitor), | |
| 223 done_count_(done_count), | |
| 224 wait_(wait) {} | |
| 225 | |
| 226 virtual void Run() { | |
| 227 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask); | |
| 228 { | |
| 229 Thread* thread = Thread::Current(); | |
| 230 *thread_ptr_ = thread; | |
| 231 CreateStackZones(id_); | |
| 232 } | |
| 233 Thread::ExitIsolateAsHelper(); | |
| 234 // Notify the main thread that this thread has exited. | |
| 235 { | |
| 236 MonitorLocker ml(monitor_); | |
| 237 *done_count_ += 1; | |
| 238 ml.Notify(); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 private: | |
| 243 void CreateStackZones(intptr_t num) { | |
| 244 Thread* thread = Thread::Current(); | |
| 245 *thread_ptr_ = thread; | |
| 246 | |
| 247 StackZone stack_zone(thread); | |
| 248 HANDLESCOPE(thread); | |
| 249 Zone* zone = thread->zone(); | |
| 250 EXPECT_EQ(zone, stack_zone.GetZone()); | |
| 251 | |
| 252 // Create a zone (which is also a stack resource) and exercise it a bit. | |
| 253 ZoneGrowableArray<bool>* a0 = new (zone) ZoneGrowableArray<bool>(zone, 1); | |
| 254 GrowableArray<bool> a1(zone, 1); | |
| 255 for (intptr_t i = 0; i < 1000 * num + id_; ++i) { | |
| 256 a0->Add(true); | |
| 257 a1.Add(true); | |
| 258 } | |
| 259 | |
| 260 num -= 1; | |
| 261 if (num != 0) { | |
| 262 CreateStackZones(num); | |
| 263 return; | |
| 264 } | |
| 265 { | |
| 266 // Let the main thread know we're done with memory ops on this thread. | |
| 267 MonitorLocker ml(monitor_); | |
| 268 *done_count_ += 1; | |
| 269 ml.Notify(); | |
| 270 } | |
| 271 // Wait for the go-ahead from the main thread to exit. | |
| 272 { | |
| 273 MonitorLocker sync_ml(sync_); | |
| 274 while (*wait_) { | |
| 275 sync_ml.Wait(); | |
| 276 } | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 intptr_t id_; | |
| 281 Isolate* isolate_; | |
| 282 Thread** thread_ptr_; | |
| 283 Monitor* sync_; | |
| 284 Monitor* monitor_; | |
| 285 intptr_t* done_count_; | |
| 286 bool* wait_; | |
| 287 }; | |
| 288 | |
| 289 | |
| 290 TEST_CASE(ManySimpleTasksWithZones) { | |
| 291 const int kTaskCount = 10; | |
| 292 Monitor monitor; | |
| 293 Monitor sync; | |
| 294 Thread* threads[kTaskCount + 1]; | |
| 295 Isolate* isolate = Thread::Current()->isolate(); | |
| 296 intptr_t done_count = 0; | |
| 297 bool wait = true; | |
| 298 threads[kTaskCount] = Thread::Current(); | |
| 299 | |
| 300 EXPECT(isolate->heap()->GrowthControlState()); | |
| 301 isolate->heap()->DisableGrowthControl(); | |
| 302 for (intptr_t i = 0; i < kTaskCount; i++) { | |
| 303 Dart::thread_pool()->Run(new SimpleTaskWithZoneAllocation( | |
| 304 (i + 1), isolate, &threads[i], &sync, &monitor, &done_count, &wait)); | |
| 305 } | |
| 306 // Wait until all spawned tasks finish their memory operations. | |
| 307 { | |
| 308 MonitorLocker ml(&monitor); | |
| 309 while (done_count < kTaskCount) { | |
| 310 ml.Wait(); | |
| 311 } | |
| 312 // Reset the done counter for use later. | |
| 313 done_count = 0; | |
| 314 } | |
| 315 | |
| 316 JSONStream stream; | |
| 317 Service::PrintJSONForVM(&stream, false); | |
| 318 const char* json = stream.ToCString(); | |
| 319 | |
| 320 // Confirm all expected entries are in the JSON output. | |
| 321 for (intptr_t i = 0; i < kTaskCount + 1; i++) { | |
| 322 Thread* thread = threads[i]; | |
| 323 Isolate* thread_isolate = thread->isolate(); | |
| 324 // Buffer can handle any possible input length given types. | |
| 325 char thread_address_buf[96]; | |
| 326 char isolate_address_buf[64]; | |
|
siva
2016/12/09 02:49:39
Instead of using a local buffer with a number that
bkonyi
2016/12/09 17:52:57
Done.
| |
| 327 Zone* top_zone = thread->zone(); | |
| 328 | |
| 329 // Check that all zones are present with correct sizes. | |
| 330 while (top_zone != NULL) { | |
| 331 char zone_info_buf[96]; | |
| 332 OS::SNPrint(zone_info_buf, sizeof(zone_info_buf), | |
| 333 "\"type\":\"_Zone\"," | |
| 334 "\"capacity\":%ld," | |
| 335 "\"used\":%ld", | |
| 336 top_zone->SizeInBytes(), top_zone->UsedSizeInBytes()); | |
| 337 | |
| 338 EXPECT_SUBSTRING(zone_info_buf, json); | |
| 339 top_zone = top_zone->previous(); | |
| 340 } | |
| 341 | |
| 342 // Check the thread exists and is the correct size. | |
| 343 OS::SNPrint(thread_address_buf, sizeof(thread_address_buf), | |
| 344 "\"type\":\"_Thread\"," | |
| 345 "\"id\":\"threads\\/%" Pd64 "", | |
| 346 thread->os_thread()->trace_id()); | |
| 347 | |
| 348 // Ensure the isolate for each thread is valid. | |
| 349 OS::SNPrint(isolate_address_buf, sizeof(isolate_address_buf), | |
| 350 "\"type\":\"Isolate\"," | |
| 351 "\"fixedId\":true," | |
| 352 "\"id\":\"isolates\\/%" Pd64 "", | |
| 353 static_cast<int64_t>(thread_isolate->main_port())); | |
| 354 | |
| 355 EXPECT_SUBSTRING(thread_address_buf, json); | |
| 356 EXPECT_SUBSTRING(isolate_address_buf, json); | |
| 357 } | |
| 358 | |
| 359 // Unblock the tasks so they can finish. | |
| 360 { | |
| 361 MonitorLocker sync_ml(&sync); | |
| 362 wait = false; | |
| 363 sync_ml.NotifyAll(); | |
| 364 } | |
| 365 // Now wait for them all to exit before destroying the isolate. | |
| 366 { | |
| 367 MonitorLocker ml(&monitor); | |
| 368 while (done_count < kTaskCount) { | |
| 369 ml.Wait(); | |
| 370 } | |
| 371 } | |
| 372 } | |
| 373 #endif | |
| 374 | |
| 375 | |
| 208 TEST_CASE(ThreadRegistry) { | 376 TEST_CASE(ThreadRegistry) { |
| 209 Isolate* orig = Thread::Current()->isolate(); | 377 Isolate* orig = Thread::Current()->isolate(); |
| 210 Zone* orig_zone = Thread::Current()->zone(); | 378 Zone* orig_zone = Thread::Current()->zone(); |
| 211 char* orig_str = orig_zone->PrintToString("foo"); | 379 char* orig_str = orig_zone->PrintToString("foo"); |
| 212 Dart_ExitIsolate(); | 380 Dart_ExitIsolate(); |
| 213 // Create and enter a new isolate. | 381 // Create and enter a new isolate. |
| 214 Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, | 382 Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, |
| 215 NULL); | 383 NULL); |
| 216 Zone* zone0 = Thread::Current()->zone(); | 384 Zone* zone0 = Thread::Current()->zone(); |
| 217 EXPECT(zone0 != orig_zone); | 385 EXPECT(zone0 != orig_zone); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 625 TransitionVMToBlocked transition(thread); | 793 TransitionVMToBlocked transition(thread); |
| 626 MonitorLocker ml(&done_monitor); | 794 MonitorLocker ml(&done_monitor); |
| 627 if (done) { | 795 if (done) { |
| 628 break; | 796 break; |
| 629 } | 797 } |
| 630 } | 798 } |
| 631 } | 799 } |
| 632 } | 800 } |
| 633 | 801 |
| 634 } // namespace dart | 802 } // namespace dart |
| OLD | NEW |