Mercurial > hg > truffle
comparison src/share/vm/services/memTracker.cpp @ 6231:7e5976e66c62
7182543: NMT ON: Aggregate a few NMT related bugs
Summary: 1) Fixed MemTrackWorker::generations_in_used() calculation 2) Ensured NMT not to leak memory recorders after shutdown 3) Used ThreadCritical to block safepoint safe threads
Reviewed-by: acorn, coleenp, dholmes, kvn
author | zgu |
---|---|
date | Thu, 19 Jul 2012 09:05:42 -0400 |
parents | d2a62e0f25eb |
children | d5bc62fcfac7 |
comparison
equal
deleted
inserted
replaced
6201:ace99a6ffc83 | 6231:7e5976e66c62 |
---|---|
349 thread = ThreadLocalStorage::thread(); | 349 thread = ThreadLocalStorage::thread(); |
350 } | 350 } |
351 } | 351 } |
352 | 352 |
353 if (thread != NULL) { | 353 if (thread != NULL) { |
354 #ifdef ASSERT | |
355 // cause assertion on stack base. This ensures that threads call | |
356 // Thread::record_stack_base_and_size() method, which will create | |
357 // thread native stack records. | |
358 thread->stack_base(); | |
359 #endif | |
360 // for a JavaThread, if it is running in native state, we need to transition it to | |
361 // VM state, so it can stop at safepoint. JavaThread running in VM state does not | |
362 // need lock to write records. | |
363 if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { | 354 if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { |
364 if (((JavaThread*)thread)->thread_state() == _thread_in_native) { | 355 JavaThread* java_thread = static_cast<JavaThread*>(thread); |
365 ThreadInVMfromNative trans((JavaThread*)thread); | 356 JavaThreadState state = java_thread->thread_state(); |
366 create_record_in_recorder(addr, flags, size, pc, thread); | 357 if (SafepointSynchronize::safepoint_safe(java_thread, state)) { |
358 // JavaThreads that are safepoint safe, can run through safepoint, | |
359 // so ThreadCritical is needed to ensure no threads at safepoint create | |
360 // new records while the records are being gathered and the sequence number is changing | |
361 ThreadCritical tc; | |
362 create_record_in_recorder(addr, flags, size, pc, java_thread); | |
367 } else { | 363 } else { |
368 create_record_in_recorder(addr, flags, size, pc, thread); | 364 create_record_in_recorder(addr, flags, size, pc, java_thread); |
369 } | 365 } |
370 } else { | 366 } else { |
371 // other threads, such as worker and watcher threads, etc. need to | 367 // other threads, such as worker and watcher threads, etc. need to |
372 // take ThreadCritical to write to global recorder | 368 // take ThreadCritical to write to global recorder |
373 ThreadCritical tc; | 369 ThreadCritical tc; |
388 } | 384 } |
389 | 385 |
390 // write a record to proper recorder. No lock can be taken from this method | 386 // write a record to proper recorder. No lock can be taken from this method |
391 // down. | 387 // down. |
392 void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, | 388 void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, |
393 size_t size, address pc, Thread* thread) { | 389 size_t size, address pc, JavaThread* thread) { |
394 assert(thread == NULL || thread->is_Java_thread(), "wrong thread"); | 390 |
395 | 391 MemRecorder* rc = get_thread_recorder(thread); |
396 MemRecorder* rc = get_thread_recorder((JavaThread*)thread); | |
397 if (rc != NULL) { | 392 if (rc != NULL) { |
398 rc->record(addr, flags, size, pc); | 393 rc->record(addr, flags, size, pc); |
399 } | 394 } |
400 } | 395 } |
401 | 396 |
458 _sync_point_skip_count ++; | 453 _sync_point_skip_count ++; |
459 return; | 454 return; |
460 } | 455 } |
461 } | 456 } |
462 _sync_point_skip_count = 0; | 457 _sync_point_skip_count = 0; |
463 // walk all JavaThreads to collect recorders | |
464 SyncThreadRecorderClosure stc; | |
465 Threads::threads_do(&stc); | |
466 | |
467 _thread_count = stc.get_thread_count(); | |
468 MemRecorder* pending_recorders = get_pending_recorders(); | |
469 | |
470 { | 458 { |
471 // This method is running at safepoint, with ThreadCritical lock, | 459 // This method is running at safepoint, with ThreadCritical lock, |
472 // it should guarantee that NMT is fully sync-ed. | 460 // it should guarantee that NMT is fully sync-ed. |
473 ThreadCritical tc; | 461 ThreadCritical tc; |
462 | |
463 // walk all JavaThreads to collect recorders | |
464 SyncThreadRecorderClosure stc; | |
465 Threads::threads_do(&stc); | |
466 | |
467 _thread_count = stc.get_thread_count(); | |
468 MemRecorder* pending_recorders = get_pending_recorders(); | |
469 | |
474 if (_global_recorder != NULL) { | 470 if (_global_recorder != NULL) { |
475 _global_recorder->set_next(pending_recorders); | 471 _global_recorder->set_next(pending_recorders); |
476 pending_recorders = _global_recorder; | 472 pending_recorders = _global_recorder; |
477 _global_recorder = NULL; | 473 _global_recorder = NULL; |
478 } | 474 } |
484 } | 480 } |
485 } | 481 } |
486 | 482 |
487 // now, it is the time to shut whole things off | 483 // now, it is the time to shut whole things off |
488 if (_state == NMT_final_shutdown) { | 484 if (_state == NMT_final_shutdown) { |
489 _tracking_level = NMT_off; | |
490 | |
491 // walk all JavaThreads to delete all recorders | 485 // walk all JavaThreads to delete all recorders |
492 SyncThreadRecorderClosure stc; | 486 SyncThreadRecorderClosure stc; |
493 Threads::threads_do(&stc); | 487 Threads::threads_do(&stc); |
494 // delete global recorder | 488 // delete global recorder |
495 { | 489 { |
497 if (_global_recorder != NULL) { | 491 if (_global_recorder != NULL) { |
498 delete _global_recorder; | 492 delete _global_recorder; |
499 _global_recorder = NULL; | 493 _global_recorder = NULL; |
500 } | 494 } |
501 } | 495 } |
502 | 496 MemRecorder* pending_recorders = get_pending_recorders(); |
503 _state = NMT_shutdown; | 497 if (pending_recorders != NULL) { |
498 delete pending_recorders; | |
499 } | |
500 // try at a later sync point to ensure MemRecorder instance drops to zero to | |
501 // completely shutdown NMT | |
502 if (MemRecorder::_instance_count == 0) { | |
503 _state = NMT_shutdown; | |
504 _tracking_level = NMT_off; | |
505 } | |
504 } | 506 } |
505 } | 507 } |
506 | 508 |
507 /* | 509 /* |
508 * Start worker thread. | 510 * Start worker thread. |