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]; |
| 327 Zone* top_zone = thread->zone(); |
| 328 |
| 329 Thread* current_thread = Thread::Current(); |
| 330 StackZone stack_zone(current_thread); |
| 331 Zone* current_zone = current_thread->zone(); |
| 332 |
| 333 // Check that all zones are present with correct sizes. |
| 334 while (top_zone != NULL) { |
| 335 char* zone_info_buf = |
| 336 OS::SCreate(current_zone, |
| 337 "\"type\":\"_Zone\"," |
| 338 "\"capacity\":%ld," |
| 339 "\"used\":%ld", |
| 340 top_zone->SizeInBytes(), top_zone->UsedSizeInBytes()); |
| 341 EXPECT_SUBSTRING(zone_info_buf, json); |
| 342 top_zone = top_zone->previous(); |
| 343 } |
| 344 |
| 345 // Check the thread exists and is the correct size. |
| 346 char* thread_info_buf = OS::SCreate(current_zone, |
| 347 "\"type\":\"_Thread\"," |
| 348 "\"id\":\"threads\\/%" Pd64 "", |
| 349 thread->os_thread()->trace_id()); |
| 350 |
| 351 // Ensure the isolate for each thread is valid. |
| 352 |
| 353 char* isolate_info_buf = |
| 354 OS::SCreate(current_zone, |
| 355 "\"type\":\"Isolate\"," |
| 356 "\"fixedId\":true," |
| 357 "\"id\":\"isolates\\/%" Pd64 "", |
| 358 static_cast<int64_t>(thread_isolate->main_port())); |
| 359 |
| 360 EXPECT_SUBSTRING(thread_info_buf, json); |
| 361 EXPECT_SUBSTRING(isolate_info_buf, json); |
| 362 } |
| 363 |
| 364 // Unblock the tasks so they can finish. |
| 365 { |
| 366 MonitorLocker sync_ml(&sync); |
| 367 wait = false; |
| 368 sync_ml.NotifyAll(); |
| 369 } |
| 370 // Now wait for them all to exit before destroying the isolate. |
| 371 { |
| 372 MonitorLocker ml(&monitor); |
| 373 while (done_count < kTaskCount) { |
| 374 ml.Wait(); |
| 375 } |
| 376 } |
| 377 } |
| 378 #endif |
| 379 |
| 380 |
208 TEST_CASE(ThreadRegistry) { | 381 TEST_CASE(ThreadRegistry) { |
209 Isolate* orig = Thread::Current()->isolate(); | 382 Isolate* orig = Thread::Current()->isolate(); |
210 Zone* orig_zone = Thread::Current()->zone(); | 383 Zone* orig_zone = Thread::Current()->zone(); |
211 char* orig_str = orig_zone->PrintToString("foo"); | 384 char* orig_str = orig_zone->PrintToString("foo"); |
212 Dart_ExitIsolate(); | 385 Dart_ExitIsolate(); |
213 // Create and enter a new isolate. | 386 // Create and enter a new isolate. |
214 Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, | 387 Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, |
215 NULL); | 388 NULL); |
216 Zone* zone0 = Thread::Current()->zone(); | 389 Zone* zone0 = Thread::Current()->zone(); |
217 EXPECT(zone0 != orig_zone); | 390 EXPECT(zone0 != orig_zone); |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 TransitionVMToBlocked transition(thread); | 798 TransitionVMToBlocked transition(thread); |
626 MonitorLocker ml(&done_monitor); | 799 MonitorLocker ml(&done_monitor); |
627 if (done) { | 800 if (done) { |
628 break; | 801 break; |
629 } | 802 } |
630 } | 803 } |
631 } | 804 } |
632 } | 805 } |
633 | 806 |
634 } // namespace dart | 807 } // namespace dart |
OLD | NEW |