1.1 --- a/src/share/vm/services/memTracker.cpp Mon Jun 10 10:45:19 2013 -0400 1.2 +++ b/src/share/vm/services/memTracker.cpp Tue Jun 18 08:44:08 2013 -0400 1.3 @@ -69,6 +69,7 @@ 1.4 volatile jint MemTracker::_pooled_recorder_count = 0; 1.5 volatile unsigned long MemTracker::_processing_generation = 0; 1.6 volatile bool MemTracker::_worker_thread_idle = false; 1.7 +volatile jint MemTracker::_pending_op_count = 0; 1.8 volatile bool MemTracker::_slowdown_calling_thread = false; 1.9 debug_only(intx MemTracker::_main_thread_tid = 0;) 1.10 NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) 1.11 @@ -337,92 +338,14 @@ 1.12 Atomic::inc(&_pooled_recorder_count); 1.13 } 1.14 1.15 -/* 1.16 - * This is the most important method in whole nmt implementation. 1.17 - * 1.18 - * Create a memory record. 1.19 - * 1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM 1.20 - * still in single thread mode. 1.21 - * 2. For all threads other than JavaThread, ThreadCritical is needed 1.22 - * to write to recorders to global recorder. 1.23 - * 3. For JavaThreads that are not longer visible by safepoint, also 1.24 - * need to take ThreadCritical and records are written to global 1.25 - * recorders, since these threads are NOT walked by Threads.do_thread(). 1.26 - * 4. JavaThreads that are running in native state, have to transition 1.27 - * to VM state before writing to per-thread recorders. 1.28 - * 5. JavaThreads that are running in VM state do not need any lock and 1.29 - * records are written to per-thread recorders. 1.30 - * 6. For a thread has yet to attach VM 'Thread', they need to take 1.31 - * ThreadCritical to write to global recorder. 1.32 - * 1.33 - * Important note: 1.34 - * NO LOCK should be taken inside ThreadCritical lock !!! 1.35 - */ 1.36 -void MemTracker::create_memory_record(address addr, MEMFLAGS flags, 1.37 - size_t size, address pc, Thread* thread) { 1.38 - assert(addr != NULL, "Sanity check"); 1.39 - if (!shutdown_in_progress()) { 1.40 - // single thread, we just write records direct to global recorder,' 1.41 - // with any lock 1.42 - if (_state == NMT_bootstrapping_single_thread) { 1.43 - assert(_main_thread_tid == os::current_thread_id(), "wrong thread"); 1.44 - thread = NULL; 1.45 - } else { 1.46 - if (thread == NULL) { 1.47 - // don't use Thread::current(), since it is possible that 1.48 - // the calling thread has yet to attach to VM 'Thread', 1.49 - // which will result assertion failure 1.50 - thread = ThreadLocalStorage::thread(); 1.51 - } 1.52 - } 1.53 - 1.54 - if (thread != NULL) { 1.55 - // slow down all calling threads except NMT worker thread, so it 1.56 - // can catch up. 1.57 - if (_slowdown_calling_thread && thread != _worker_thread) { 1.58 - os::yield_all(); 1.59 - } 1.60 - 1.61 - if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { 1.62 - JavaThread* java_thread = (JavaThread*)thread; 1.63 - JavaThreadState state = java_thread->thread_state(); 1.64 - if (SafepointSynchronize::safepoint_safe(java_thread, state)) { 1.65 - // JavaThreads that are safepoint safe, can run through safepoint, 1.66 - // so ThreadCritical is needed to ensure no threads at safepoint create 1.67 - // new records while the records are being gathered and the sequence number is changing 1.68 - ThreadCritical tc; 1.69 - create_record_in_recorder(addr, flags, size, pc, java_thread); 1.70 - } else { 1.71 - create_record_in_recorder(addr, flags, size, pc, java_thread); 1.72 - } 1.73 - } else { 1.74 - // other threads, such as worker and watcher threads, etc. need to 1.75 - // take ThreadCritical to write to global recorder 1.76 - ThreadCritical tc; 1.77 - create_record_in_recorder(addr, flags, size, pc, NULL); 1.78 - } 1.79 - } else { 1.80 - if (_state == NMT_bootstrapping_single_thread) { 1.81 - // single thread, no lock needed 1.82 - create_record_in_recorder(addr, flags, size, pc, NULL); 1.83 - } else { 1.84 - // for thread has yet to attach VM 'Thread', we can not use VM mutex. 1.85 - // use native thread critical instead 1.86 - ThreadCritical tc; 1.87 - create_record_in_recorder(addr, flags, size, pc, NULL); 1.88 - } 1.89 - } 1.90 - } 1.91 -} 1.92 - 1.93 // write a record to proper recorder. No lock can be taken from this method 1.94 // down. 1.95 -void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, 1.96 - size_t size, address pc, JavaThread* thread) { 1.97 +void MemTracker::write_tracking_record(address addr, MEMFLAGS flags, 1.98 + size_t size, jint seq, address pc, JavaThread* thread) { 1.99 1.100 MemRecorder* rc = get_thread_recorder(thread); 1.101 if (rc != NULL) { 1.102 - rc->record(addr, flags, size, pc); 1.103 + rc->record(addr, flags, size, seq, pc); 1.104 } 1.105 } 1.106 1.107 @@ -487,39 +410,43 @@ 1.108 return; 1.109 } 1.110 } 1.111 - _sync_point_skip_count = 0; 1.112 { 1.113 // This method is running at safepoint, with ThreadCritical lock, 1.114 // it should guarantee that NMT is fully sync-ed. 1.115 ThreadCritical tc; 1.116 1.117 - SequenceGenerator::reset(); 1.118 + // We can NOT execute NMT sync-point if there are pending tracking ops. 1.119 + if (_pending_op_count == 0) { 1.120 + SequenceGenerator::reset(); 1.121 + _sync_point_skip_count = 0; 1.122 1.123 - // walk all JavaThreads to collect recorders 1.124 - SyncThreadRecorderClosure stc; 1.125 - Threads::threads_do(&stc); 1.126 + // walk all JavaThreads to collect recorders 1.127 + SyncThreadRecorderClosure stc; 1.128 + Threads::threads_do(&stc); 1.129 1.130 - _thread_count = stc.get_thread_count(); 1.131 - MemRecorder* pending_recorders = get_pending_recorders(); 1.132 + _thread_count = stc.get_thread_count(); 1.133 + MemRecorder* pending_recorders = get_pending_recorders(); 1.134 1.135 - if (_global_recorder != NULL) { 1.136 - _global_recorder->set_next(pending_recorders); 1.137 - pending_recorders = _global_recorder; 1.138 - _global_recorder = NULL; 1.139 + if (_global_recorder != NULL) { 1.140 + _global_recorder->set_next(pending_recorders); 1.141 + pending_recorders = _global_recorder; 1.142 + _global_recorder = NULL; 1.143 + } 1.144 + 1.145 + // see if NMT has too many outstanding recorder instances, it usually 1.146 + // means that worker thread is lagging behind in processing them. 1.147 + if (!AutoShutdownNMT) { 1.148 + _slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count); 1.149 + } 1.150 + 1.151 + // check _worker_thread with lock to avoid racing condition 1.152 + if (_worker_thread != NULL) { 1.153 + _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes()); 1.154 + } 1.155 + assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point"); 1.156 + } else { 1.157 + _sync_point_skip_count ++; 1.158 } 1.159 - 1.160 - // see if NMT has too many outstanding recorder instances, it usually 1.161 - // means that worker thread is lagging behind in processing them. 1.162 - if (!AutoShutdownNMT) { 1.163 - _slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count); 1.164 - } 1.165 - 1.166 - // check _worker_thread with lock to avoid racing condition 1.167 - if (_worker_thread != NULL) { 1.168 - _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes()); 1.169 - } 1.170 - 1.171 - assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point"); 1.172 } 1.173 } 1.174 1.175 @@ -708,3 +635,243 @@ 1.176 } 1.177 #endif 1.178 1.179 + 1.180 +// Tracker Implementation 1.181 + 1.182 +/* 1.183 + * Create a tracker. 1.184 + * This is a fairly complicated constructor, as it has to make two important decisions: 1.185 + * 1) Does it need to take ThreadCritical lock to write tracking record 1.186 + * 2) Does it need to pre-reserve a sequence number for the tracking record 1.187 + * 1.188 + * The rules to determine if ThreadCritical is needed: 1.189 + * 1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM 1.190 + * still in single thread mode. 1.191 + * 2. For all threads other than JavaThread, ThreadCritical is needed 1.192 + * to write to recorders to global recorder. 1.193 + * 3. For JavaThreads that are no longer visible by safepoint, also 1.194 + * need to take ThreadCritical and records are written to global 1.195 + * recorders, since these threads are NOT walked by Threads.do_thread(). 1.196 + * 4. JavaThreads that are running in safepoint-safe states do not stop 1.197 + * for safepoints, ThreadCritical lock should be taken to write 1.198 + * memory records. 1.199 + * 5. JavaThreads that are running in VM state do not need any lock and 1.200 + * records are written to per-thread recorders. 1.201 + * 6. For a thread has yet to attach VM 'Thread', they need to take 1.202 + * ThreadCritical to write to global recorder. 1.203 + * 1.204 + * The memory operations that need pre-reserve sequence numbers: 1.205 + * The memory operations that "release" memory blocks and the 1.206 + * operations can fail, need to pre-reserve sequence number. They 1.207 + * are realloc, uncommit and release. 1.208 + * 1.209 + * The reason for pre-reserve sequence number, is to prevent race condition: 1.210 + * Thread 1 Thread 2 1.211 + * <release> 1.212 + * <allocate> 1.213 + * <write allocate record> 1.214 + * <write release record> 1.215 + * if Thread 2 happens to obtain the memory address Thread 1 just released, 1.216 + * then NMT can mistakenly report the memory is free. 1.217 + * 1.218 + * Noticeably, free() does not need pre-reserve sequence number, because the call 1.219 + * does not fail, so we can alway write "release" record before the memory is actaully 1.220 + * freed. 1.221 + * 1.222 + * For realloc, uncommit and release, following coding pattern should be used: 1.223 + * 1.224 + * MemTracker::Tracker tkr = MemTracker::get_realloc_tracker(); 1.225 + * ptr = ::realloc(...); 1.226 + * if (ptr == NULL) { 1.227 + * tkr.record(...) 1.228 + * } else { 1.229 + * tkr.discard(); 1.230 + * } 1.231 + * 1.232 + * MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); 1.233 + * if (uncommit(...)) { 1.234 + * tkr.record(...); 1.235 + * } else { 1.236 + * tkr.discard(); 1.237 + * } 1.238 + * 1.239 + * MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); 1.240 + * if (release(...)) { 1.241 + * tkr.record(...); 1.242 + * } else { 1.243 + * tkr.discard(); 1.244 + * } 1.245 + * 1.246 + * Since pre-reserved sequence number is only good for the generation that it is acquired, 1.247 + * when there is pending Tracker that reserved sequence number, NMT sync-point has 1.248 + * to be skipped to prevent from advancing generation. This is done by inc and dec 1.249 + * MemTracker::_pending_op_count, when MemTracker::_pending_op_count > 0, NMT sync-point is skipped. 1.250 + * Not all pre-reservation of sequence number will increment pending op count. For JavaThreads 1.251 + * that honor safepoints, safepoint can not occur during the memory operations, so the 1.252 + * pre-reserved sequence number won't cross the generation boundry. 1.253 + */ 1.254 +MemTracker::Tracker::Tracker(MemoryOperation op, Thread* thr) { 1.255 + _op = NoOp; 1.256 + _seq = 0; 1.257 + if (MemTracker::is_on()) { 1.258 + _java_thread = NULL; 1.259 + _op = op; 1.260 + 1.261 + // figure out if ThreadCritical lock is needed to write this operation 1.262 + // to MemTracker 1.263 + if (MemTracker::is_single_threaded_bootstrap()) { 1.264 + thr = NULL; 1.265 + } else if (thr == NULL) { 1.266 + // don't use Thread::current(), since it is possible that 1.267 + // the calling thread has yet to attach to VM 'Thread', 1.268 + // which will result assertion failure 1.269 + thr = ThreadLocalStorage::thread(); 1.270 + } 1.271 + 1.272 + if (thr != NULL) { 1.273 + // Check NMT load 1.274 + MemTracker::check_NMT_load(thr); 1.275 + 1.276 + if (thr->is_Java_thread() && ((JavaThread*)thr)->is_safepoint_visible()) { 1.277 + _java_thread = (JavaThread*)thr; 1.278 + JavaThreadState state = _java_thread->thread_state(); 1.279 + // JavaThreads that are safepoint safe, can run through safepoint, 1.280 + // so ThreadCritical is needed to ensure no threads at safepoint create 1.281 + // new records while the records are being gathered and the sequence number is changing 1.282 + _need_thread_critical_lock = 1.283 + SafepointSynchronize::safepoint_safe(_java_thread, state); 1.284 + } else { 1.285 + _need_thread_critical_lock = true; 1.286 + } 1.287 + } else { 1.288 + _need_thread_critical_lock 1.289 + = !MemTracker::is_single_threaded_bootstrap(); 1.290 + } 1.291 + 1.292 + // see if we need to pre-reserve sequence number for this operation 1.293 + if (_op == Realloc || _op == Uncommit || _op == Release) { 1.294 + if (_need_thread_critical_lock) { 1.295 + ThreadCritical tc; 1.296 + MemTracker::inc_pending_op_count(); 1.297 + _seq = SequenceGenerator::next(); 1.298 + } else { 1.299 + // for the threads that honor safepoints, no safepoint can occur 1.300 + // during the lifespan of tracker, so we don't need to increase 1.301 + // pending op count. 1.302 + _seq = SequenceGenerator::next(); 1.303 + } 1.304 + } 1.305 + } 1.306 +} 1.307 + 1.308 +void MemTracker::Tracker::discard() { 1.309 + if (MemTracker::is_on() && _seq != 0) { 1.310 + if (_need_thread_critical_lock) { 1.311 + ThreadCritical tc; 1.312 + MemTracker::dec_pending_op_count(); 1.313 + } 1.314 + _seq = 0; 1.315 + } 1.316 +} 1.317 + 1.318 + 1.319 +void MemTracker::Tracker::record(address old_addr, address new_addr, size_t size, 1.320 + MEMFLAGS flags, address pc) { 1.321 + assert(old_addr != NULL && new_addr != NULL, "Sanity check"); 1.322 + assert(_op == Realloc || _op == NoOp, "Wrong call"); 1.323 + if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) { 1.324 + assert(_seq > 0, "Need pre-reserve sequence number"); 1.325 + if (_need_thread_critical_lock) { 1.326 + ThreadCritical tc; 1.327 + // free old address, use pre-reserved sequence number 1.328 + MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), 1.329 + 0, _seq, pc, _java_thread); 1.330 + MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), 1.331 + size, SequenceGenerator::next(), pc, _java_thread); 1.332 + // decrement MemTracker pending_op_count 1.333 + MemTracker::dec_pending_op_count(); 1.334 + } else { 1.335 + // free old address, use pre-reserved sequence number 1.336 + MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), 1.337 + 0, _seq, pc, _java_thread); 1.338 + MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), 1.339 + size, SequenceGenerator::next(), pc, _java_thread); 1.340 + } 1.341 + _seq = 0; 1.342 + } 1.343 +} 1.344 + 1.345 +void MemTracker::Tracker::record(address addr, size_t size, MEMFLAGS flags, address pc) { 1.346 + // OOM already? 1.347 + if (addr == NULL) return; 1.348 + 1.349 + if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) { 1.350 + bool pre_reserved_seq = (_seq != 0); 1.351 + address pc = CALLER_CALLER_PC; 1.352 + MEMFLAGS orig_flags = flags; 1.353 + 1.354 + // or the tagging flags 1.355 + switch(_op) { 1.356 + case Malloc: 1.357 + flags |= MemPointerRecord::malloc_tag(); 1.358 + break; 1.359 + case Free: 1.360 + flags = MemPointerRecord::free_tag(); 1.361 + break; 1.362 + case Realloc: 1.363 + fatal("Use the other Tracker::record()"); 1.364 + break; 1.365 + case Reserve: 1.366 + case ReserveAndCommit: 1.367 + flags |= MemPointerRecord::virtual_memory_reserve_tag(); 1.368 + break; 1.369 + case Commit: 1.370 + flags = MemPointerRecord::virtual_memory_commit_tag(); 1.371 + break; 1.372 + case Type: 1.373 + flags |= MemPointerRecord::virtual_memory_type_tag(); 1.374 + break; 1.375 + case Uncommit: 1.376 + assert(pre_reserved_seq, "Need pre-reserve sequence number"); 1.377 + flags = MemPointerRecord::virtual_memory_uncommit_tag(); 1.378 + break; 1.379 + case Release: 1.380 + assert(pre_reserved_seq, "Need pre-reserve sequence number"); 1.381 + flags = MemPointerRecord::virtual_memory_release_tag(); 1.382 + break; 1.383 + case ArenaSize: 1.384 + // a bit of hack here, add a small postive offset to arena 1.385 + // address for its size record, so the size record is sorted 1.386 + // right after arena record. 1.387 + flags = MemPointerRecord::arena_size_tag(); 1.388 + addr += sizeof(void*); 1.389 + break; 1.390 + case StackRelease: 1.391 + flags = MemPointerRecord::virtual_memory_release_tag(); 1.392 + break; 1.393 + default: 1.394 + ShouldNotReachHere(); 1.395 + } 1.396 + 1.397 + // write memory tracking record 1.398 + if (_need_thread_critical_lock) { 1.399 + ThreadCritical tc; 1.400 + if (_seq == 0) _seq = SequenceGenerator::next(); 1.401 + MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); 1.402 + if (_op == ReserveAndCommit) { 1.403 + MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), 1.404 + size, SequenceGenerator::next(), pc, _java_thread); 1.405 + } 1.406 + if (pre_reserved_seq) MemTracker::dec_pending_op_count(); 1.407 + } else { 1.408 + if (_seq == 0) _seq = SequenceGenerator::next(); 1.409 + MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); 1.410 + if (_op == ReserveAndCommit) { 1.411 + MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), 1.412 + size, SequenceGenerator::next(), pc, _java_thread); 1.413 + } 1.414 + } 1.415 + _seq = 0; 1.416 + } 1.417 +} 1.418 +