author | zgu |
Tue, 18 Jun 2013 08:44:08 -0400 | |
changeset 18086 | f44cf213a775 |
parent 17838 | 89e464689cb1 |
child 18929 | 063c1b9097af |
child 18743 | ffe61257d9a0 |
permissions | -rw-r--r-- |
13195 | 1 |
/* |
16671
2685f312df3f
8011161: NMT: Memory leak when encountering out of memory error while initializing memory snapshot
zgu
parents:
16436
diff
changeset
|
2 |
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
13195 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
22 |
* |
|
23 |
*/ |
|
24 |
#include "precompiled.hpp" |
|
25 |
||
15104
f5d78994619f
8005048: NMT: #loaded classes needs to just show the # defined classes
zgu
parents:
14575
diff
changeset
|
26 |
#include "oops/instanceKlass.hpp" |
13195 | 27 |
#include "runtime/atomic.hpp" |
28 |
#include "runtime/interfaceSupport.hpp" |
|
29 |
#include "runtime/mutexLocker.hpp" |
|
30 |
#include "runtime/safepoint.hpp" |
|
31 |
#include "runtime/threadCritical.hpp" |
|
15452
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
32 |
#include "runtime/vm_operations.hpp" |
13195 | 33 |
#include "services/memPtr.hpp" |
34 |
#include "services/memReporter.hpp" |
|
35 |
#include "services/memTracker.hpp" |
|
36 |
#include "utilities/decoder.hpp" |
|
17838
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
37 |
#include "utilities/defaultStream.hpp" |
13195 | 38 |
#include "utilities/globalDefinitions.hpp" |
39 |
||
40 |
bool NMT_track_callsite = false; |
|
41 |
||
42 |
// walk all 'known' threads at NMT sync point, and collect their recorders |
|
43 |
void SyncThreadRecorderClosure::do_thread(Thread* thread) { |
|
44 |
assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); |
|
45 |
if (thread->is_Java_thread()) { |
|
46 |
JavaThread* javaThread = (JavaThread*)thread; |
|
47 |
MemRecorder* recorder = javaThread->get_recorder(); |
|
48 |
if (recorder != NULL) { |
|
49 |
MemTracker::enqueue_pending_recorder(recorder); |
|
50 |
javaThread->set_recorder(NULL); |
|
51 |
} |
|
52 |
} |
|
53 |
_thread_count ++; |
|
54 |
} |
|
55 |
||
56 |
||
16991
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
57 |
MemRecorder* volatile MemTracker::_global_recorder = NULL; |
13195 | 58 |
MemSnapshot* MemTracker::_snapshot = NULL; |
59 |
MemBaseline MemTracker::_baseline; |
|
13301
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
60 |
Mutex* MemTracker::_query_lock = NULL; |
16991
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
61 |
MemRecorder* volatile MemTracker::_merge_pending_queue = NULL; |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
62 |
MemRecorder* volatile MemTracker::_pooled_recorders = NULL; |
13195 | 63 |
MemTrackWorker* MemTracker::_worker_thread = NULL; |
64 |
int MemTracker::_sync_point_skip_count = 0; |
|
65 |
MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off; |
|
66 |
volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; |
|
67 |
MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; |
|
68 |
int MemTracker::_thread_count = 255; |
|
69 |
volatile jint MemTracker::_pooled_recorder_count = 0; |
|
15452
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
70 |
volatile unsigned long MemTracker::_processing_generation = 0; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
71 |
volatile bool MemTracker::_worker_thread_idle = false; |
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
72 |
volatile jint MemTracker::_pending_op_count = 0; |
16436
6b67e51e3cfb
8009298: NMT: Special version of class loading/unloading with runThese stresses out NMT
zgu
parents:
15452
diff
changeset
|
73 |
volatile bool MemTracker::_slowdown_calling_thread = false; |
13195 | 74 |
debug_only(intx MemTracker::_main_thread_tid = 0;) |
13478
85fe611440e5
7191124: Optimized build is broken due to inconsistent use of DEBUG_ONLY and NOT_PRODUCT macros in NMT
zgu
parents:
13304
diff
changeset
|
75 |
NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) |
13195 | 76 |
|
77 |
void MemTracker::init_tracking_options(const char* option_line) { |
|
78 |
_tracking_level = NMT_off; |
|
14575
be194f2e2ba1
8003689: MemTracker::init_tracking_options() reads outside array if commandline argument is empty
zgu
parents:
14120
diff
changeset
|
79 |
if (strcmp(option_line, "=summary") == 0) { |
13195 | 80 |
_tracking_level = NMT_summary; |
14575
be194f2e2ba1
8003689: MemTracker::init_tracking_options() reads outside array if commandline argument is empty
zgu
parents:
14120
diff
changeset
|
81 |
} else if (strcmp(option_line, "=detail") == 0) { |
17838
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
82 |
// detail relies on a stack-walking ability that may not |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
83 |
// be available depending on platform and/or compiler flags |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
84 |
if (PLATFORM_NMT_DETAIL_SUPPORTED) { |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
85 |
_tracking_level = NMT_detail; |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
86 |
} else { |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
87 |
jio_fprintf(defaultStream::error_stream(), |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
88 |
"NMT detail is not supported on this platform. Using NMT summary instead."); |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
89 |
_tracking_level = NMT_summary; |
89e464689cb1
8011064: Some tests have failed with SIGSEGV on arm-hflt on build b82
jprovino
parents:
17074
diff
changeset
|
90 |
} |
14575
be194f2e2ba1
8003689: MemTracker::init_tracking_options() reads outside array if commandline argument is empty
zgu
parents:
14120
diff
changeset
|
91 |
} else if (strcmp(option_line, "=off") != 0) { |
be194f2e2ba1
8003689: MemTracker::init_tracking_options() reads outside array if commandline argument is empty
zgu
parents:
14120
diff
changeset
|
92 |
vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); |
13195 | 93 |
} |
94 |
} |
|
95 |
||
96 |
// first phase of bootstrapping, when VM is still in single-threaded mode. |
|
97 |
void MemTracker::bootstrap_single_thread() { |
|
98 |
if (_tracking_level > NMT_off) { |
|
99 |
assert(_state == NMT_uninited, "wrong state"); |
|
100 |
||
101 |
// NMT is not supported with UseMallocOnly is on. NMT can NOT |
|
102 |
// handle the amount of malloc data without significantly impacting |
|
103 |
// runtime performance when this flag is on. |
|
104 |
if (UseMallocOnly) { |
|
105 |
shutdown(NMT_use_malloc_only); |
|
106 |
return; |
|
107 |
} |
|
108 |
||
13301
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
109 |
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); |
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
110 |
if (_query_lock == NULL) { |
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
111 |
shutdown(NMT_out_of_memory); |
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
112 |
return; |
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
113 |
} |
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
114 |
|
13195 | 115 |
debug_only(_main_thread_tid = os::current_thread_id();) |
116 |
_state = NMT_bootstrapping_single_thread; |
|
117 |
NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); |
|
118 |
} |
|
119 |
} |
|
120 |
||
121 |
// second phase of bootstrapping, when VM is about to or already entered multi-theaded mode. |
|
122 |
void MemTracker::bootstrap_multi_thread() { |
|
123 |
if (_tracking_level > NMT_off && _state == NMT_bootstrapping_single_thread) { |
|
124 |
// create nmt lock for multi-thread execution |
|
125 |
assert(_main_thread_tid == os::current_thread_id(), "wrong thread"); |
|
126 |
_state = NMT_bootstrapping_multi_thread; |
|
127 |
NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); |
|
128 |
} |
|
129 |
} |
|
130 |
||
131 |
// fully start nmt |
|
132 |
void MemTracker::start() { |
|
133 |
// Native memory tracking is off from command line option |
|
134 |
if (_tracking_level == NMT_off || shutdown_in_progress()) return; |
|
135 |
||
136 |
assert(_main_thread_tid == os::current_thread_id(), "wrong thread"); |
|
137 |
assert(_state == NMT_bootstrapping_multi_thread, "wrong state"); |
|
138 |
||
139 |
_snapshot = new (std::nothrow)MemSnapshot(); |
|
16671
2685f312df3f
8011161: NMT: Memory leak when encountering out of memory error while initializing memory snapshot
zgu
parents:
16436
diff
changeset
|
140 |
if (_snapshot != NULL) { |
16991
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
141 |
if (!_snapshot->out_of_memory() && start_worker(_snapshot)) { |
13195 | 142 |
_state = NMT_started; |
143 |
NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); |
|
144 |
return; |
|
145 |
} |
|
16671
2685f312df3f
8011161: NMT: Memory leak when encountering out of memory error while initializing memory snapshot
zgu
parents:
16436
diff
changeset
|
146 |
|
2685f312df3f
8011161: NMT: Memory leak when encountering out of memory error while initializing memory snapshot
zgu
parents:
16436
diff
changeset
|
147 |
delete _snapshot; |
2685f312df3f
8011161: NMT: Memory leak when encountering out of memory error while initializing memory snapshot
zgu
parents:
16436
diff
changeset
|
148 |
_snapshot = NULL; |
13195 | 149 |
} |
150 |
||
151 |
// fail to start native memory tracking, shut it down |
|
152 |
shutdown(NMT_initialization); |
|
153 |
} |
|
154 |
||
155 |
/** |
|
156 |
* Shutting down native memory tracking. |
|
157 |
* We can not shutdown native memory tracking immediately, so we just |
|
158 |
* setup shutdown pending flag, every native memory tracking component |
|
159 |
* should orderly shut itself down. |
|
160 |
* |
|
161 |
* The shutdown sequences: |
|
162 |
* 1. MemTracker::shutdown() sets MemTracker to shutdown pending state |
|
163 |
* 2. Worker thread calls MemTracker::final_shutdown(), which transites |
|
164 |
* MemTracker to final shutdown state. |
|
165 |
* 3. At sync point, MemTracker does final cleanup, before sets memory |
|
166 |
* tracking level to off to complete shutdown. |
|
167 |
*/ |
|
168 |
void MemTracker::shutdown(ShutdownReason reason) { |
|
169 |
if (_tracking_level == NMT_off) return; |
|
170 |
||
171 |
if (_state <= NMT_bootstrapping_single_thread) { |
|
172 |
// we still in single thread mode, there is not contention |
|
173 |
_state = NMT_shutdown_pending; |
|
174 |
_reason = reason; |
|
175 |
} else { |
|
176 |
// we want to know who initialized shutdown |
|
177 |
if ((jint)NMT_started == Atomic::cmpxchg((jint)NMT_shutdown_pending, |
|
178 |
(jint*)&_state, (jint)NMT_started)) { |
|
179 |
_reason = reason; |
|
180 |
} |
|
181 |
} |
|
182 |
} |
|
183 |
||
184 |
// final phase of shutdown |
|
185 |
void MemTracker::final_shutdown() { |
|
186 |
// delete all pending recorders and pooled recorders |
|
187 |
delete_all_pending_recorders(); |
|
188 |
delete_all_pooled_recorders(); |
|
189 |
||
190 |
{ |
|
191 |
// shared baseline and snapshot are the only objects needed to |
|
192 |
// create query results |
|
13301
f6dd749390dd
7181986: NMT ON: Assertion failure when running jdi ExpiredRequestDeletionTest
zgu
parents:
13195
diff
changeset
|
193 |
MutexLockerEx locker(_query_lock, true); |
13195 | 194 |
// cleanup baseline data and snapshot |
195 |
_baseline.clear(); |
|
196 |
delete _snapshot; |
|
197 |
_snapshot = NULL; |
|
198 |
} |
|
199 |
||
200 |
// shutdown shared decoder instance, since it is only |
|
201 |
// used by native memory tracking so far. |
|
202 |
Decoder::shutdown(); |
|
203 |
||
204 |
MemTrackWorker* worker = NULL; |
|
205 |
{ |
|
206 |
ThreadCritical tc; |
|
207 |
// can not delete worker inside the thread critical |
|
208 |
if (_worker_thread != NULL && Thread::current() == _worker_thread) { |
|
209 |
worker = _worker_thread; |
|
210 |
_worker_thread = NULL; |
|
211 |
} |
|
212 |
} |
|
213 |
if (worker != NULL) { |
|
214 |
delete worker; |
|
215 |
} |
|
216 |
_state = NMT_final_shutdown; |
|
217 |
} |
|
218 |
||
219 |
// delete all pooled recorders |
|
220 |
void MemTracker::delete_all_pooled_recorders() { |
|
221 |
// free all pooled recorders |
|
16991
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
222 |
MemRecorder* volatile cur_head = _pooled_recorders; |
13195 | 223 |
if (cur_head != NULL) { |
224 |
MemRecorder* null_ptr = NULL; |
|
225 |
while (cur_head != NULL && (void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, |
|
226 |
(void*)&_pooled_recorders, (void*)cur_head)) { |
|
227 |
cur_head = _pooled_recorders; |
|
228 |
} |
|
229 |
if (cur_head != NULL) { |
|
230 |
delete cur_head; |
|
231 |
_pooled_recorder_count = 0; |
|
232 |
} |
|
233 |
} |
|
234 |
} |
|
235 |
||
236 |
// delete all recorders in pending queue |
|
237 |
void MemTracker::delete_all_pending_recorders() { |
|
238 |
// free all pending recorders |
|
239 |
MemRecorder* pending_head = get_pending_recorders(); |
|
240 |
if (pending_head != NULL) { |
|
241 |
delete pending_head; |
|
242 |
} |
|
243 |
} |
|
244 |
||
245 |
/* |
|
246 |
* retrieve per-thread recorder of specified thread. |
|
247 |
* if thread == NULL, it means global recorder |
|
248 |
*/ |
|
249 |
MemRecorder* MemTracker::get_thread_recorder(JavaThread* thread) { |
|
250 |
if (shutdown_in_progress()) return NULL; |
|
251 |
||
252 |
MemRecorder* rc; |
|
253 |
if (thread == NULL) { |
|
254 |
rc = _global_recorder; |
|
255 |
} else { |
|
256 |
rc = thread->get_recorder(); |
|
257 |
} |
|
258 |
||
259 |
if (rc != NULL && rc->is_full()) { |
|
260 |
enqueue_pending_recorder(rc); |
|
261 |
rc = NULL; |
|
262 |
} |
|
263 |
||
264 |
if (rc == NULL) { |
|
265 |
rc = get_new_or_pooled_instance(); |
|
266 |
if (thread == NULL) { |
|
267 |
_global_recorder = rc; |
|
268 |
} else { |
|
269 |
thread->set_recorder(rc); |
|
270 |
} |
|
271 |
} |
|
272 |
return rc; |
|
273 |
} |
|
274 |
||
275 |
/* |
|
276 |
* get a per-thread recorder from pool, or create a new one if |
|
277 |
* there is not one available. |
|
278 |
*/ |
|
279 |
MemRecorder* MemTracker::get_new_or_pooled_instance() { |
|
280 |
MemRecorder* cur_head = const_cast<MemRecorder*> (_pooled_recorders); |
|
281 |
if (cur_head == NULL) { |
|
282 |
MemRecorder* rec = new (std::nothrow)MemRecorder(); |
|
283 |
if (rec == NULL || rec->out_of_memory()) { |
|
284 |
shutdown(NMT_out_of_memory); |
|
285 |
if (rec != NULL) { |
|
286 |
delete rec; |
|
287 |
rec = NULL; |
|
288 |
} |
|
289 |
} |
|
290 |
return rec; |
|
291 |
} else { |
|
292 |
MemRecorder* next_head = cur_head->next(); |
|
293 |
if ((void*)cur_head != Atomic::cmpxchg_ptr((void*)next_head, (void*)&_pooled_recorders, |
|
294 |
(void*)cur_head)) { |
|
295 |
return get_new_or_pooled_instance(); |
|
296 |
} |
|
297 |
cur_head->set_next(NULL); |
|
298 |
Atomic::dec(&_pooled_recorder_count); |
|
15452
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
299 |
cur_head->set_generation(); |
13195 | 300 |
return cur_head; |
301 |
} |
|
302 |
} |
|
303 |
||
304 |
/* |
|
305 |
* retrieve all recorders in pending queue, and empty the queue |
|
306 |
*/ |
|
307 |
MemRecorder* MemTracker::get_pending_recorders() { |
|
308 |
MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue); |
|
309 |
MemRecorder* null_ptr = NULL; |
|
310 |
while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, (void*)&_merge_pending_queue, |
|
311 |
(void*)cur_head)) { |
|
312 |
cur_head = const_cast<MemRecorder*>(_merge_pending_queue); |
|
313 |
} |
|
13478
85fe611440e5
7191124: Optimized build is broken due to inconsistent use of DEBUG_ONLY and NOT_PRODUCT macros in NMT
zgu
parents:
13304
diff
changeset
|
314 |
NOT_PRODUCT(Atomic::store(0, &_pending_recorder_count)); |
13195 | 315 |
return cur_head; |
316 |
} |
|
317 |
||
318 |
/* |
|
319 |
* release a recorder to recorder pool. |
|
320 |
*/ |
|
321 |
void MemTracker::release_thread_recorder(MemRecorder* rec) { |
|
322 |
assert(rec != NULL, "null recorder"); |
|
323 |
// we don't want to pool too many recorders |
|
324 |
rec->set_next(NULL); |
|
325 |
if (shutdown_in_progress() || _pooled_recorder_count > _thread_count * 2) { |
|
326 |
delete rec; |
|
327 |
return; |
|
328 |
} |
|
329 |
||
330 |
rec->clear(); |
|
331 |
MemRecorder* cur_head = const_cast<MemRecorder*>(_pooled_recorders); |
|
332 |
rec->set_next(cur_head); |
|
333 |
while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_pooled_recorders, |
|
334 |
(void*)cur_head)) { |
|
335 |
cur_head = const_cast<MemRecorder*>(_pooled_recorders); |
|
336 |
rec->set_next(cur_head); |
|
337 |
} |
|
338 |
Atomic::inc(&_pooled_recorder_count); |
|
339 |
} |
|
340 |
||
341 |
// write a record to proper recorder. No lock can be taken from this method |
|
342 |
// down. |
|
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
343 |
void MemTracker::write_tracking_record(address addr, MEMFLAGS flags, |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
344 |
size_t size, jint seq, address pc, JavaThread* thread) { |
13195 | 345 |
|
13300 | 346 |
MemRecorder* rc = get_thread_recorder(thread); |
13195 | 347 |
if (rc != NULL) { |
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
348 |
rc->record(addr, flags, size, seq, pc); |
13195 | 349 |
} |
350 |
} |
|
351 |
||
352 |
/** |
|
353 |
* enqueue a recorder to pending queue |
|
354 |
*/ |
|
355 |
void MemTracker::enqueue_pending_recorder(MemRecorder* rec) { |
|
356 |
assert(rec != NULL, "null recorder"); |
|
357 |
||
358 |
// we are shutting down, so just delete it |
|
359 |
if (shutdown_in_progress()) { |
|
360 |
rec->set_next(NULL); |
|
361 |
delete rec; |
|
362 |
return; |
|
363 |
} |
|
364 |
||
365 |
MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue); |
|
366 |
rec->set_next(cur_head); |
|
367 |
while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_merge_pending_queue, |
|
368 |
(void*)cur_head)) { |
|
369 |
cur_head = const_cast<MemRecorder*>(_merge_pending_queue); |
|
370 |
rec->set_next(cur_head); |
|
371 |
} |
|
13478
85fe611440e5
7191124: Optimized build is broken due to inconsistent use of DEBUG_ONLY and NOT_PRODUCT macros in NMT
zgu
parents:
13304
diff
changeset
|
372 |
NOT_PRODUCT(Atomic::inc(&_pending_recorder_count);) |
13195 | 373 |
} |
374 |
||
375 |
/* |
|
376 |
* The method is called at global safepoint |
|
377 |
* during it synchronization process. |
|
378 |
* 1. enqueue all JavaThreads' per-thread recorders |
|
379 |
* 2. enqueue global recorder |
|
380 |
* 3. retrieve all pending recorders |
|
381 |
* 4. reset global sequence number generator |
|
382 |
* 5. call worker's sync |
|
383 |
*/ |
|
384 |
#define MAX_SAFEPOINTS_TO_SKIP 128 |
|
385 |
#define SAFE_SEQUENCE_THRESHOLD 30 |
|
386 |
#define HIGH_GENERATION_THRESHOLD 60 |
|
16436
6b67e51e3cfb
8009298: NMT: Special version of class loading/unloading with runThese stresses out NMT
zgu
parents:
15452
diff
changeset
|
387 |
#define MAX_RECORDER_THREAD_RATIO 30 |
13195 | 388 |
|
389 |
void MemTracker::sync() { |
|
390 |
assert(_tracking_level > NMT_off, "NMT is not enabled"); |
|
391 |
assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); |
|
392 |
||
393 |
// Some GC tests hit large number of safepoints in short period of time |
|
394 |
// without meaningful activities. We should prevent going to |
|
395 |
// sync point in these cases, which can potentially exhaust generation buffer. |
|
396 |
// Here is the factots to determine if we should go into sync point: |
|
397 |
// 1. not to overflow sequence number |
|
398 |
// 2. if we are in danger to overflow generation buffer |
|
399 |
// 3. how many safepoints we already skipped sync point |
|
400 |
if (_state == NMT_started) { |
|
401 |
// worker thread is not ready, no one can manage generation |
|
402 |
// buffer, so skip this safepoint |
|
403 |
if (_worker_thread == NULL) return; |
|
404 |
||
405 |
if (_sync_point_skip_count < MAX_SAFEPOINTS_TO_SKIP) { |
|
406 |
int per_seq_in_use = SequenceGenerator::peek() * 100 / max_jint; |
|
407 |
int per_gen_in_use = _worker_thread->generations_in_use() * 100 / MAX_GENERATIONS; |
|
408 |
if (per_seq_in_use < SAFE_SEQUENCE_THRESHOLD && per_gen_in_use >= HIGH_GENERATION_THRESHOLD) { |
|
409 |
_sync_point_skip_count ++; |
|
410 |
return; |
|
411 |
} |
|
412 |
} |
|
413 |
{ |
|
414 |
// This method is running at safepoint, with ThreadCritical lock, |
|
415 |
// it should guarantee that NMT is fully sync-ed. |
|
416 |
ThreadCritical tc; |
|
13300 | 417 |
|
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
418 |
// We can NOT execute NMT sync-point if there are pending tracking ops. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
419 |
if (_pending_op_count == 0) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
420 |
SequenceGenerator::reset(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
421 |
_sync_point_skip_count = 0; |
14120
7d298141c258
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
13872
diff
changeset
|
422 |
|
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
423 |
// walk all JavaThreads to collect recorders |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
424 |
SyncThreadRecorderClosure stc; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
425 |
Threads::threads_do(&stc); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
426 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
427 |
_thread_count = stc.get_thread_count(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
428 |
MemRecorder* pending_recorders = get_pending_recorders(); |
13300 | 429 |
|
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
430 |
if (_global_recorder != NULL) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
431 |
_global_recorder->set_next(pending_recorders); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
432 |
pending_recorders = _global_recorder; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
433 |
_global_recorder = NULL; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
434 |
} |
13300 | 435 |
|
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
436 |
// see if NMT has too many outstanding recorder instances, it usually |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
437 |
// means that worker thread is lagging behind in processing them. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
438 |
if (!AutoShutdownNMT) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
439 |
_slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
440 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
441 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
442 |
// check _worker_thread with lock to avoid racing condition |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
443 |
if (_worker_thread != NULL) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
444 |
_worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes()); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
445 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
446 |
assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
447 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
448 |
_sync_point_skip_count ++; |
13195 | 449 |
} |
450 |
} |
|
451 |
} |
|
452 |
||
453 |
// now, it is the time to shut whole things off |
|
454 |
if (_state == NMT_final_shutdown) { |
|
455 |
// walk all JavaThreads to delete all recorders |
|
456 |
SyncThreadRecorderClosure stc; |
|
457 |
Threads::threads_do(&stc); |
|
458 |
// delete global recorder |
|
459 |
{ |
|
460 |
ThreadCritical tc; |
|
461 |
if (_global_recorder != NULL) { |
|
462 |
delete _global_recorder; |
|
463 |
_global_recorder = NULL; |
|
464 |
} |
|
465 |
} |
|
13300 | 466 |
MemRecorder* pending_recorders = get_pending_recorders(); |
467 |
if (pending_recorders != NULL) { |
|
468 |
delete pending_recorders; |
|
469 |
} |
|
470 |
// try at a later sync point to ensure MemRecorder instance drops to zero to |
|
471 |
// completely shutdown NMT |
|
472 |
if (MemRecorder::_instance_count == 0) { |
|
473 |
_state = NMT_shutdown; |
|
474 |
_tracking_level = NMT_off; |
|
475 |
} |
|
13195 | 476 |
} |
477 |
} |
|
478 |
||
479 |
/* |
|
480 |
* Start worker thread. |
|
481 |
*/ |
|
16991
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
482 |
bool MemTracker::start_worker(MemSnapshot* snapshot) { |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
483 |
assert(_worker_thread == NULL && _snapshot != NULL, "Just Check"); |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
484 |
_worker_thread = new (std::nothrow) MemTrackWorker(snapshot); |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
485 |
if (_worker_thread == NULL) { |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
486 |
return false; |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
487 |
} else if (_worker_thread->has_error()) { |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
488 |
delete _worker_thread; |
aa4978a77e1f
8010151: nsk/regression/b6653214 fails "assert(snapshot != NULL) failed: Worker should not be started"
zgu
parents:
16671
diff
changeset
|
489 |
_worker_thread = NULL; |
13195 | 490 |
return false; |
491 |
} |
|
492 |
_worker_thread->start(); |
|
493 |
return true; |
|
494 |
} |
|
495 |
||
496 |
/* |
|
497 |
* We need to collect a JavaThread's per-thread recorder |
|
498 |
* before it exits. |
|
499 |
*/ |
|
500 |
void MemTracker::thread_exiting(JavaThread* thread) { |
|
501 |
if (is_on()) { |
|
502 |
MemRecorder* rec = thread->get_recorder(); |
|
503 |
if (rec != NULL) { |
|
504 |
enqueue_pending_recorder(rec); |
|
505 |
thread->set_recorder(NULL); |
|
506 |
} |
|
507 |
} |
|
508 |
} |
|
509 |
||
510 |
// baseline current memory snapshot |
|
511 |
bool MemTracker::baseline() { |
|
17074 | 512 |
MutexLocker lock(_query_lock); |
13195 | 513 |
MemSnapshot* snapshot = get_snapshot(); |
514 |
if (snapshot != NULL) { |
|
515 |
return _baseline.baseline(*snapshot, false); |
|
516 |
} |
|
517 |
return false; |
|
518 |
} |
|
519 |
||
520 |
// print memory usage from current snapshot |
|
521 |
bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { |
|
522 |
MemBaseline baseline; |
|
17074 | 523 |
MutexLocker lock(_query_lock); |
13195 | 524 |
MemSnapshot* snapshot = get_snapshot(); |
525 |
if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { |
|
526 |
BaselineReporter reporter(out, unit); |
|
527 |
reporter.report_baseline(baseline, summary_only); |
|
528 |
return true; |
|
529 |
} |
|
530 |
return false; |
|
531 |
} |
|
532 |
||
15452
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
533 |
// Whitebox API for blocking until the current generation of NMT data has been merged |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
534 |
bool MemTracker::wbtest_wait_for_data_merge() { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
535 |
// NMT can't be shutdown while we're holding _query_lock |
17074 | 536 |
MutexLocker lock(_query_lock); |
15452
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
537 |
assert(_worker_thread != NULL, "Invalid query"); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
538 |
// the generation at query time, so NMT will spin till this generation is processed |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
539 |
unsigned long generation_at_query_time = SequenceGenerator::current_generation(); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
540 |
unsigned long current_processing_generation = _processing_generation; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
541 |
// if generation counter overflown |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
542 |
bool generation_overflown = (generation_at_query_time < current_processing_generation); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
543 |
long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
544 |
// spin |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
545 |
while (!shutdown_in_progress()) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
546 |
if (!generation_overflown) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
547 |
if (current_processing_generation > generation_at_query_time) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
548 |
return true; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
549 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
550 |
} else { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
551 |
assert(generations_to_wrap >= 0, "Sanity check"); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
552 |
long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
553 |
assert(current_generations_to_wrap >= 0, "Sanity check"); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
554 |
// to overflow an unsigned long should take long time, so to_wrap check should be sufficient |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
555 |
if (current_generations_to_wrap > generations_to_wrap && |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
556 |
current_processing_generation > generation_at_query_time) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
557 |
return true; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
558 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
559 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
560 |
|
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
561 |
// if worker thread is idle, but generation is not advancing, that means |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
562 |
// there is not safepoint to let NMT advance generation, force one. |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
563 |
if (_worker_thread_idle) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
564 |
VM_ForceSafepoint vfs; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
565 |
VMThread::execute(&vfs); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
566 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
567 |
MemSnapshot* snapshot = get_snapshot(); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
568 |
if (snapshot == NULL) { |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
569 |
return false; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
570 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
571 |
snapshot->wait(1000); |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
572 |
current_processing_generation = _processing_generation; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
573 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
574 |
// We end up here if NMT is shutting down before our data has been merged |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
575 |
return false; |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
576 |
} |
3bfde2dea09d
8005012: Add WB APIs to better support NMT testing
ctornqvi
parents:
15104
diff
changeset
|
577 |
|
13195 | 578 |
// compare memory usage between current snapshot and baseline |
579 |
bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { |
|
17074 | 580 |
MutexLocker lock(_query_lock); |
13195 | 581 |
if (_baseline.baselined()) { |
582 |
MemBaseline baseline; |
|
583 |
MemSnapshot* snapshot = get_snapshot(); |
|
584 |
if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { |
|
585 |
BaselineReporter reporter(out, unit); |
|
586 |
reporter.diff_baselines(baseline, _baseline, summary_only); |
|
587 |
return true; |
|
588 |
} |
|
589 |
} |
|
590 |
return false; |
|
591 |
} |
|
592 |
||
593 |
#ifndef PRODUCT |
|
594 |
void MemTracker::walk_stack(int toSkip, char* buf, int len) { |
|
595 |
int cur_len = 0; |
|
596 |
char tmp[1024]; |
|
597 |
address pc; |
|
598 |
||
599 |
while (cur_len < len) { |
|
600 |
pc = os::get_caller_pc(toSkip + 1); |
|
601 |
if (pc != NULL && os::dll_address_to_function_name(pc, tmp, sizeof(tmp), NULL)) { |
|
602 |
jio_snprintf(&buf[cur_len], (len - cur_len), "%s\n", tmp); |
|
603 |
cur_len = (int)strlen(buf); |
|
604 |
} else { |
|
605 |
buf[cur_len] = '\0'; |
|
606 |
break; |
|
607 |
} |
|
608 |
toSkip ++; |
|
609 |
} |
|
610 |
} |
|
611 |
||
612 |
void MemTracker::print_tracker_stats(outputStream* st) { |
|
613 |
st->print_cr("\nMemory Tracker Stats:"); |
|
614 |
st->print_cr("\tMax sequence number = %d", SequenceGenerator::max_seq_num()); |
|
615 |
st->print_cr("\tthead count = %d", _thread_count); |
|
616 |
st->print_cr("\tArena instance = %d", Arena::_instance_count); |
|
617 |
st->print_cr("\tpooled recorder count = %d", _pooled_recorder_count); |
|
618 |
st->print_cr("\tqueued recorder count = %d", _pending_recorder_count); |
|
619 |
st->print_cr("\tmemory recorder instance count = %d", MemRecorder::_instance_count); |
|
620 |
if (_worker_thread != NULL) { |
|
621 |
st->print_cr("\tWorker thread:"); |
|
622 |
st->print_cr("\t\tSync point count = %d", _worker_thread->_sync_point_count); |
|
623 |
st->print_cr("\t\tpending recorder count = %d", _worker_thread->count_pending_recorders()); |
|
624 |
st->print_cr("\t\tmerge count = %d", _worker_thread->_merge_count); |
|
625 |
} else { |
|
626 |
st->print_cr("\tWorker thread is not started"); |
|
627 |
} |
|
628 |
st->print_cr(" "); |
|
629 |
||
630 |
if (_snapshot != NULL) { |
|
631 |
_snapshot->print_snapshot_stats(st); |
|
632 |
} else { |
|
633 |
st->print_cr("No snapshot"); |
|
634 |
} |
|
635 |
} |
|
636 |
#endif |
|
637 |
||
18086
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
638 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
639 |
// Tracker Implementation |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
640 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
641 |
/* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
642 |
* Create a tracker. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
643 |
* This is a fairly complicated constructor, as it has to make two important decisions: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
644 |
* 1) Does it need to take ThreadCritical lock to write tracking record |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
645 |
* 2) Does it need to pre-reserve a sequence number for the tracking record |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
646 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
647 |
* The rules to determine if ThreadCritical is needed: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
648 |
* 1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
649 |
* still in single thread mode. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
650 |
* 2. For all threads other than JavaThread, ThreadCritical is needed |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
651 |
* to write to recorders to global recorder. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
652 |
* 3. For JavaThreads that are no longer visible by safepoint, also |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
653 |
* need to take ThreadCritical and records are written to global |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
654 |
* recorders, since these threads are NOT walked by Threads.do_thread(). |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
655 |
* 4. JavaThreads that are running in safepoint-safe states do not stop |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
656 |
* for safepoints, ThreadCritical lock should be taken to write |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
657 |
* memory records. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
658 |
* 5. JavaThreads that are running in VM state do not need any lock and |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
659 |
* records are written to per-thread recorders. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
660 |
* 6. For a thread has yet to attach VM 'Thread', they need to take |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
661 |
* ThreadCritical to write to global recorder. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
662 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
663 |
* The memory operations that need pre-reserve sequence numbers: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
664 |
* The memory operations that "release" memory blocks and the |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
665 |
* operations can fail, need to pre-reserve sequence number. They |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
666 |
* are realloc, uncommit and release. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
667 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
668 |
* The reason for pre-reserve sequence number, is to prevent race condition: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
669 |
* Thread 1 Thread 2 |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
670 |
* <release> |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
671 |
* <allocate> |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
672 |
* <write allocate record> |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
673 |
* <write release record> |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
674 |
* if Thread 2 happens to obtain the memory address Thread 1 just released, |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
675 |
* then NMT can mistakenly report the memory is free. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
676 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
677 |
* Noticeably, free() does not need pre-reserve sequence number, because the call |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
678 |
* does not fail, so we can alway write "release" record before the memory is actaully |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
679 |
* freed. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
680 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
681 |
* For realloc, uncommit and release, following coding pattern should be used: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
682 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
683 |
* MemTracker::Tracker tkr = MemTracker::get_realloc_tracker(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
684 |
* ptr = ::realloc(...); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
685 |
* if (ptr == NULL) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
686 |
* tkr.record(...) |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
687 |
* } else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
688 |
* tkr.discard(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
689 |
* } |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
690 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
691 |
* MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
692 |
* if (uncommit(...)) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
693 |
* tkr.record(...); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
694 |
* } else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
695 |
* tkr.discard(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
696 |
* } |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
697 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
698 |
* MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
699 |
* if (release(...)) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
700 |
* tkr.record(...); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
701 |
* } else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
702 |
* tkr.discard(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
703 |
* } |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
704 |
* |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
705 |
* Since pre-reserved sequence number is only good for the generation that it is acquired, |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
706 |
* when there is pending Tracker that reserved sequence number, NMT sync-point has |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
707 |
* to be skipped to prevent from advancing generation. This is done by inc and dec |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
708 |
* MemTracker::_pending_op_count, when MemTracker::_pending_op_count > 0, NMT sync-point is skipped. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
709 |
* Not all pre-reservation of sequence number will increment pending op count. For JavaThreads |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
710 |
* that honor safepoints, safepoint can not occur during the memory operations, so the |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
711 |
* pre-reserved sequence number won't cross the generation boundry. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
712 |
*/ |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
713 |
MemTracker::Tracker::Tracker(MemoryOperation op, Thread* thr) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
714 |
_op = NoOp; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
715 |
_seq = 0; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
716 |
if (MemTracker::is_on()) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
717 |
_java_thread = NULL; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
718 |
_op = op; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
719 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
720 |
// figure out if ThreadCritical lock is needed to write this operation |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
721 |
// to MemTracker |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
722 |
if (MemTracker::is_single_threaded_bootstrap()) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
723 |
thr = NULL; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
724 |
} else if (thr == NULL) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
725 |
// don't use Thread::current(), since it is possible that |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
726 |
// the calling thread has yet to attach to VM 'Thread', |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
727 |
// which will result assertion failure |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
728 |
thr = ThreadLocalStorage::thread(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
729 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
730 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
731 |
if (thr != NULL) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
732 |
// Check NMT load |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
733 |
MemTracker::check_NMT_load(thr); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
734 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
735 |
if (thr->is_Java_thread() && ((JavaThread*)thr)->is_safepoint_visible()) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
736 |
_java_thread = (JavaThread*)thr; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
737 |
JavaThreadState state = _java_thread->thread_state(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
738 |
// JavaThreads that are safepoint safe, can run through safepoint, |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
739 |
// so ThreadCritical is needed to ensure no threads at safepoint create |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
740 |
// new records while the records are being gathered and the sequence number is changing |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
741 |
_need_thread_critical_lock = |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
742 |
SafepointSynchronize::safepoint_safe(_java_thread, state); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
743 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
744 |
_need_thread_critical_lock = true; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
745 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
746 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
747 |
_need_thread_critical_lock |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
748 |
= !MemTracker::is_single_threaded_bootstrap(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
749 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
750 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
751 |
// see if we need to pre-reserve sequence number for this operation |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
752 |
if (_op == Realloc || _op == Uncommit || _op == Release) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
753 |
if (_need_thread_critical_lock) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
754 |
ThreadCritical tc; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
755 |
MemTracker::inc_pending_op_count(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
756 |
_seq = SequenceGenerator::next(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
757 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
758 |
// for the threads that honor safepoints, no safepoint can occur |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
759 |
// during the lifespan of tracker, so we don't need to increase |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
760 |
// pending op count. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
761 |
_seq = SequenceGenerator::next(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
762 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
763 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
764 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
765 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
766 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
767 |
void MemTracker::Tracker::discard() { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
768 |
if (MemTracker::is_on() && _seq != 0) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
769 |
if (_need_thread_critical_lock) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
770 |
ThreadCritical tc; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
771 |
MemTracker::dec_pending_op_count(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
772 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
773 |
_seq = 0; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
774 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
775 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
776 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
777 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
778 |
void MemTracker::Tracker::record(address old_addr, address new_addr, size_t size, |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
779 |
MEMFLAGS flags, address pc) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
780 |
assert(old_addr != NULL && new_addr != NULL, "Sanity check"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
781 |
assert(_op == Realloc || _op == NoOp, "Wrong call"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
782 |
if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
783 |
assert(_seq > 0, "Need pre-reserve sequence number"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
784 |
if (_need_thread_critical_lock) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
785 |
ThreadCritical tc; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
786 |
// free old address, use pre-reserved sequence number |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
787 |
MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
788 |
0, _seq, pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
789 |
MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
790 |
size, SequenceGenerator::next(), pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
791 |
// decrement MemTracker pending_op_count |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
792 |
MemTracker::dec_pending_op_count(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
793 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
794 |
// free old address, use pre-reserved sequence number |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
795 |
MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
796 |
0, _seq, pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
797 |
MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
798 |
size, SequenceGenerator::next(), pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
799 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
800 |
_seq = 0; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
801 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
802 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
803 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
804 |
void MemTracker::Tracker::record(address addr, size_t size, MEMFLAGS flags, address pc) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
805 |
// OOM already? |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
806 |
if (addr == NULL) return; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
807 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
808 |
if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
809 |
bool pre_reserved_seq = (_seq != 0); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
810 |
address pc = CALLER_CALLER_PC; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
811 |
MEMFLAGS orig_flags = flags; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
812 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
813 |
// or the tagging flags |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
814 |
switch(_op) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
815 |
case Malloc: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
816 |
flags |= MemPointerRecord::malloc_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
817 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
818 |
case Free: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
819 |
flags = MemPointerRecord::free_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
820 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
821 |
case Realloc: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
822 |
fatal("Use the other Tracker::record()"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
823 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
824 |
case Reserve: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
825 |
case ReserveAndCommit: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
826 |
flags |= MemPointerRecord::virtual_memory_reserve_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
827 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
828 |
case Commit: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
829 |
flags = MemPointerRecord::virtual_memory_commit_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
830 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
831 |
case Type: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
832 |
flags |= MemPointerRecord::virtual_memory_type_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
833 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
834 |
case Uncommit: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
835 |
assert(pre_reserved_seq, "Need pre-reserve sequence number"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
836 |
flags = MemPointerRecord::virtual_memory_uncommit_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
837 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
838 |
case Release: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
839 |
assert(pre_reserved_seq, "Need pre-reserve sequence number"); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
840 |
flags = MemPointerRecord::virtual_memory_release_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
841 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
842 |
case ArenaSize: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
843 |
// a bit of hack here, add a small postive offset to arena |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
844 |
// address for its size record, so the size record is sorted |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
845 |
// right after arena record. |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
846 |
flags = MemPointerRecord::arena_size_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
847 |
addr += sizeof(void*); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
848 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
849 |
case StackRelease: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
850 |
flags = MemPointerRecord::virtual_memory_release_tag(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
851 |
break; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
852 |
default: |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
853 |
ShouldNotReachHere(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
854 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
855 |
|
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
856 |
// write memory tracking record |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
857 |
if (_need_thread_critical_lock) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
858 |
ThreadCritical tc; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
859 |
if (_seq == 0) _seq = SequenceGenerator::next(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
860 |
MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
861 |
if (_op == ReserveAndCommit) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
862 |
MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
863 |
size, SequenceGenerator::next(), pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
864 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
865 |
if (pre_reserved_seq) MemTracker::dec_pending_op_count(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
866 |
} else { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
867 |
if (_seq == 0) _seq = SequenceGenerator::next(); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
868 |
MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
869 |
if (_op == ReserveAndCommit) { |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
870 |
MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
871 |
size, SequenceGenerator::next(), pc, _java_thread); |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
872 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
873 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
874 |
_seq = 0; |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
875 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
876 |
} |
f44cf213a775
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
17838
diff
changeset
|
877 |