author | chegar |
Thu, 17 Oct 2019 20:54:25 +0100 | |
branch | datagramsocketimpl-branch |
changeset 58679 | 9c3209ff7550 |
parent 58678 | 9cf78a70fa4f |
parent 58132 | caa25ab47aca |
permissions | -rw-r--r-- |
50113 | 1 |
/* |
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
2 |
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
50113 | 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 |
||
25 |
#include "precompiled.hpp" |
|
26 |
#include "jfr/jni/jfrJavaSupport.hpp" |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
27 |
#include "jfr/leakprofiler/leakProfiler.hpp" |
50113 | 28 |
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp" |
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
29 |
#include "jfr/leakprofiler/sampling/objectSampler.hpp" |
50113 | 30 |
#include "jfr/recorder/jfrRecorder.hpp" |
31 |
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" |
|
32 |
#include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp" |
|
53014
339d2fbe8675
8215284: Reduce noise induced by periodic task getFileSize()
mgronlun
parents:
52877
diff
changeset
|
33 |
#include "jfr/recorder/repository/jfrChunkRotation.hpp" |
50113 | 34 |
#include "jfr/recorder/repository/jfrChunkWriter.hpp" |
35 |
#include "jfr/recorder/repository/jfrRepository.hpp" |
|
36 |
#include "jfr/recorder/service/jfrPostBox.hpp" |
|
37 |
#include "jfr/recorder/service/jfrRecorderService.hpp" |
|
38 |
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" |
|
39 |
#include "jfr/recorder/storage/jfrStorage.hpp" |
|
40 |
#include "jfr/recorder/storage/jfrStorageControl.hpp" |
|
41 |
#include "jfr/recorder/stringpool/jfrStringPool.hpp" |
|
42 |
#include "jfr/utilities/jfrAllocation.hpp" |
|
43 |
#include "jfr/utilities/jfrTime.hpp" |
|
44 |
#include "jfr/writers/jfrJavaEventWriter.hpp" |
|
45 |
#include "jfr/utilities/jfrTypes.hpp" |
|
46 |
#include "logging/log.hpp" |
|
47 |
#include "memory/resourceArea.hpp" |
|
48 |
#include "runtime/atomic.hpp" |
|
49 |
#include "runtime/handles.inline.hpp" |
|
50 |
#include "runtime/mutexLocker.hpp" |
|
50429
83aec1d357d4
8204301: Make OrderAccess functions available to hpp rather than inline.hpp files
coleenp
parents:
50113
diff
changeset
|
51 |
#include "runtime/orderAccess.hpp" |
50113 | 52 |
#include "runtime/os.hpp" |
53 |
#include "runtime/safepoint.hpp" |
|
54 |
#include "runtime/thread.inline.hpp" |
|
52877
9e041366c764
8214850: Rename vm_operations.?pp files to vmOperations.?pp files
tschatzl
parents:
51334
diff
changeset
|
55 |
#include "runtime/vmOperations.hpp" |
50113 | 56 |
#include "runtime/vmThread.hpp" |
57 |
||
58 |
// set data iff *dest == NULL |
|
59 |
static bool try_set(void* const data, void** dest, bool clear) { |
|
60 |
assert(data != NULL, "invariant"); |
|
61 |
const void* const current = OrderAccess::load_acquire(dest); |
|
62 |
if (current != NULL) { |
|
63 |
if (current != data) { |
|
64 |
// already set |
|
65 |
return false; |
|
66 |
} |
|
67 |
assert(current == data, "invariant"); |
|
68 |
if (!clear) { |
|
69 |
// recursion disallowed |
|
70 |
return false; |
|
71 |
} |
|
72 |
} |
|
73 |
return Atomic::cmpxchg(clear ? NULL : data, dest, current) == current; |
|
74 |
} |
|
75 |
||
76 |
static void* rotation_thread = NULL; |
|
77 |
static const int rotation_try_limit = 1000; |
|
78 |
static const int rotation_retry_sleep_millis = 10; |
|
79 |
||
80 |
class RotationLock : public StackObj { |
|
81 |
private: |
|
82 |
Thread* const _thread; |
|
83 |
bool _acquired; |
|
84 |
||
85 |
void log(bool recursion) { |
|
86 |
assert(!_acquired, "invariant"); |
|
87 |
const char* error_msg = NULL; |
|
88 |
if (recursion) { |
|
89 |
error_msg = "Unable to issue rotation due to recursive calls."; |
|
90 |
} |
|
91 |
else { |
|
92 |
error_msg = "Unable to issue rotation due to wait timeout."; |
|
93 |
} |
|
94 |
log_info(jfr)( // For user, should not be "jfr, system" |
|
95 |
"%s", error_msg); |
|
96 |
} |
|
97 |
public: |
|
98 |
RotationLock(Thread* thread) : _thread(thread), _acquired(false) { |
|
99 |
assert(_thread != NULL, "invariant"); |
|
100 |
if (_thread == rotation_thread) { |
|
101 |
// recursion not supported |
|
102 |
log(true); |
|
103 |
return; |
|
104 |
} |
|
105 |
||
106 |
// limited to not spin indefinitely |
|
107 |
for (int i = 0; i < rotation_try_limit; ++i) { |
|
108 |
if (try_set(_thread, &rotation_thread, false)) { |
|
109 |
_acquired = true; |
|
110 |
assert(_thread == rotation_thread, "invariant"); |
|
111 |
return; |
|
112 |
} |
|
113 |
if (_thread->is_Java_thread()) { |
|
114 |
// in order to allow the system to move to a safepoint |
|
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
115 |
MutexLocker msg_lock(JfrMsg_lock); |
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
116 |
JfrMsg_lock->wait(rotation_retry_sleep_millis); |
50113 | 117 |
} |
118 |
else { |
|
119 |
os::naked_short_sleep(rotation_retry_sleep_millis); |
|
120 |
} |
|
121 |
} |
|
122 |
log(false); |
|
123 |
} |
|
124 |
||
125 |
~RotationLock() { |
|
126 |
assert(_thread != NULL, "invariant"); |
|
127 |
if (_acquired) { |
|
128 |
assert(_thread == rotation_thread, "invariant"); |
|
129 |
while (!try_set(_thread, &rotation_thread, true)); |
|
130 |
} |
|
131 |
} |
|
132 |
bool not_acquired() const { return !_acquired; } |
|
133 |
}; |
|
134 |
||
53897
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
135 |
static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) { |
58132
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
136 |
const int64_t last_cp_offset = cw.last_checkpoint_offset(); |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
137 |
const int64_t delta_to_last_checkpoint = 0 == last_cp_offset ? 0 : last_cp_offset - cw.current_offset(); |
50113 | 138 |
cw.reserve(sizeof(u4)); |
139 |
cw.write<u8>(EVENT_CHECKPOINT); |
|
140 |
cw.write(JfrTicks::now()); |
|
58132
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
141 |
cw.write((int64_t)0); // duration |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
142 |
cw.write(delta_to_last_checkpoint); |
50113 | 143 |
cw.write<bool>(false); // flushpoint |
53897
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
144 |
cw.write((u4)1); // nof types in this checkpoint |
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
145 |
cw.write(type_id); |
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
146 |
const int64_t number_of_elements_offset = cw.current_offset(); |
50113 | 147 |
cw.reserve(sizeof(u4)); |
148 |
return number_of_elements_offset; |
|
149 |
} |
|
150 |
||
151 |
template <typename ContentFunctor> |
|
152 |
class WriteCheckpointEvent : public StackObj { |
|
153 |
private: |
|
154 |
JfrChunkWriter& _cw; |
|
155 |
u8 _type_id; |
|
156 |
ContentFunctor& _content_functor; |
|
157 |
public: |
|
158 |
WriteCheckpointEvent(JfrChunkWriter& cw, u8 type_id, ContentFunctor& functor) : |
|
159 |
_cw(cw), |
|
160 |
_type_id(type_id), |
|
161 |
_content_functor(functor) { |
|
162 |
assert(_cw.is_valid(), "invariant"); |
|
163 |
} |
|
164 |
bool process() { |
|
165 |
// current_cp_offset is also offset for the event size header field |
|
53897
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
166 |
const int64_t current_cp_offset = _cw.current_offset(); |
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
167 |
const int64_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id); |
50113 | 168 |
// invocation |
169 |
_content_functor.process(); |
|
170 |
const u4 number_of_elements = (u4)_content_functor.processed(); |
|
171 |
if (number_of_elements == 0) { |
|
172 |
// nothing to do, rewind writer to start |
|
173 |
_cw.seek(current_cp_offset); |
|
174 |
return true; |
|
175 |
} |
|
176 |
assert(number_of_elements > 0, "invariant"); |
|
177 |
assert(_cw.current_offset() > num_elements_offset, "invariant"); |
|
178 |
_cw.write_padded_at_offset<u4>(number_of_elements, num_elements_offset); |
|
179 |
_cw.write_padded_at_offset<u4>((u4)_cw.current_offset() - current_cp_offset, current_cp_offset); |
|
180 |
// update writer with last checkpoint position |
|
58132
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
181 |
_cw.set_last_checkpoint_offset(current_cp_offset); |
50113 | 182 |
return true; |
183 |
} |
|
184 |
}; |
|
185 |
||
186 |
template <typename Instance, size_t(Instance::*func)()> |
|
187 |
class ServiceFunctor { |
|
188 |
private: |
|
189 |
Instance& _instance; |
|
190 |
size_t _processed; |
|
191 |
public: |
|
192 |
ServiceFunctor(Instance& instance) : _instance(instance), _processed(0) {} |
|
193 |
bool process() { |
|
194 |
_processed = (_instance.*func)(); |
|
195 |
return true; |
|
196 |
} |
|
197 |
size_t processed() const { return _processed; } |
|
198 |
}; |
|
199 |
||
200 |
template <typename Instance, void(Instance::*func)()> |
|
201 |
class JfrVMOperation : public VM_Operation { |
|
202 |
private: |
|
203 |
Instance& _instance; |
|
204 |
public: |
|
205 |
JfrVMOperation(Instance& instance) : _instance(instance) {} |
|
206 |
void doit() { (_instance.*func)(); } |
|
207 |
VMOp_Type type() const { return VMOp_JFRCheckpoint; } |
|
208 |
Mode evaluation_mode() const { return _safepoint; } // default |
|
209 |
}; |
|
210 |
||
211 |
class WriteStackTraceRepository : public StackObj { |
|
212 |
private: |
|
213 |
JfrStackTraceRepository& _repo; |
|
214 |
JfrChunkWriter& _cw; |
|
215 |
size_t _elements_processed; |
|
216 |
bool _clear; |
|
217 |
||
218 |
public: |
|
219 |
WriteStackTraceRepository(JfrStackTraceRepository& repo, JfrChunkWriter& cw, bool clear) : |
|
220 |
_repo(repo), _cw(cw), _elements_processed(0), _clear(clear) {} |
|
221 |
bool process() { |
|
222 |
_elements_processed = _repo.write(_cw, _clear); |
|
223 |
return true; |
|
224 |
} |
|
225 |
size_t processed() const { return _elements_processed; } |
|
226 |
void reset() { _elements_processed = 0; } |
|
227 |
}; |
|
228 |
||
229 |
static bool recording = false; |
|
230 |
||
231 |
static void set_recording_state(bool is_recording) { |
|
232 |
OrderAccess::storestore(); |
|
233 |
recording = is_recording; |
|
234 |
} |
|
235 |
||
236 |
bool JfrRecorderService::is_recording() { |
|
237 |
return recording; |
|
238 |
} |
|
239 |
||
240 |
JfrRecorderService::JfrRecorderService() : |
|
241 |
_checkpoint_manager(JfrCheckpointManager::instance()), |
|
242 |
_chunkwriter(JfrRepository::chunkwriter()), |
|
243 |
_repository(JfrRepository::instance()), |
|
51334
cc2c79d22508
8208671: Runtime, JFR, Serviceability changes to allow enabling -Wreorder
tschatzl
parents:
50429
diff
changeset
|
244 |
_stack_trace_repository(JfrStackTraceRepository::instance()), |
50113 | 245 |
_storage(JfrStorage::instance()), |
246 |
_string_pool(JfrStringPool::instance()) {} |
|
247 |
||
248 |
void JfrRecorderService::start() { |
|
249 |
RotationLock rl(Thread::current()); |
|
250 |
if (rl.not_acquired()) { |
|
251 |
return; |
|
252 |
} |
|
253 |
log_debug(jfr, system)("Request to START recording"); |
|
254 |
assert(!is_recording(), "invariant"); |
|
255 |
clear(); |
|
256 |
set_recording_state(true); |
|
257 |
assert(is_recording(), "invariant"); |
|
258 |
open_new_chunk(); |
|
259 |
log_debug(jfr, system)("Recording STARTED"); |
|
260 |
} |
|
261 |
||
262 |
void JfrRecorderService::clear() { |
|
263 |
ResourceMark rm; |
|
264 |
HandleMark hm; |
|
265 |
pre_safepoint_clear(); |
|
266 |
invoke_safepoint_clear(); |
|
267 |
post_safepoint_clear(); |
|
268 |
} |
|
269 |
||
270 |
void JfrRecorderService::pre_safepoint_clear() { |
|
271 |
_stack_trace_repository.clear(); |
|
272 |
_string_pool.clear(); |
|
273 |
_storage.clear(); |
|
274 |
} |
|
275 |
||
276 |
void JfrRecorderService::invoke_safepoint_clear() { |
|
277 |
JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_clear> safepoint_task(*this); |
|
278 |
VMThread::execute(&safepoint_task); |
|
279 |
} |
|
280 |
||
281 |
// |
|
282 |
// safepoint clear sequence |
|
283 |
// |
|
284 |
// clear stacktrace repository -> |
|
285 |
// clear string pool -> |
|
286 |
// clear storage -> |
|
287 |
// shift epoch -> |
|
288 |
// update time |
|
289 |
// |
|
290 |
void JfrRecorderService::safepoint_clear() { |
|
291 |
assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
|
292 |
_stack_trace_repository.clear(); |
|
293 |
_string_pool.clear(); |
|
294 |
_storage.clear(); |
|
295 |
_checkpoint_manager.shift_epoch(); |
|
296 |
_chunkwriter.time_stamp_chunk_now(); |
|
297 |
} |
|
298 |
||
299 |
void JfrRecorderService::post_safepoint_clear() { |
|
300 |
_checkpoint_manager.clear(); |
|
301 |
} |
|
302 |
||
303 |
static void stop() { |
|
304 |
assert(JfrRecorderService::is_recording(), "invariant"); |
|
305 |
log_debug(jfr, system)("Recording STOPPED"); |
|
306 |
set_recording_state(false); |
|
307 |
assert(!JfrRecorderService::is_recording(), "invariant"); |
|
308 |
} |
|
309 |
||
310 |
void JfrRecorderService::rotate(int msgs) { |
|
311 |
RotationLock rl(Thread::current()); |
|
312 |
if (rl.not_acquired()) { |
|
313 |
return; |
|
314 |
} |
|
315 |
static bool vm_error = false; |
|
316 |
if (msgs & MSGBIT(MSG_VM_ERROR)) { |
|
317 |
vm_error = true; |
|
318 |
prepare_for_vm_error_rotation(); |
|
319 |
} |
|
58132
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
320 |
if (!_storage.control().to_disk()) { |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
321 |
in_memory_rotation(); |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
322 |
} else if (vm_error) { |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
323 |
vm_error_rotation(); |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
324 |
} else { |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
325 |
chunk_rotation(); |
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
326 |
} |
50113 | 327 |
if (msgs & (MSGBIT(MSG_STOP))) { |
328 |
stop(); |
|
329 |
} |
|
330 |
} |
|
331 |
||
332 |
void JfrRecorderService::prepare_for_vm_error_rotation() { |
|
333 |
if (!_chunkwriter.is_valid()) { |
|
334 |
open_new_chunk(true); |
|
335 |
} |
|
336 |
_checkpoint_manager.register_service_thread(Thread::current()); |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
337 |
JfrMetadataEvent::lock(); |
50113 | 338 |
} |
339 |
||
340 |
void JfrRecorderService::open_new_chunk(bool vm_error) { |
|
341 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
342 |
assert(!JfrStream_lock->owned_by_self(), "invariant"); |
|
53014
339d2fbe8675
8215284: Reduce noise induced by periodic task getFileSize()
mgronlun
parents:
52877
diff
changeset
|
343 |
JfrChunkRotation::on_rotation(); |
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
344 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 345 |
if (!_repository.open_chunk(vm_error)) { |
346 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
347 |
_storage.control().set_to_disk(false); |
|
348 |
return; |
|
349 |
} |
|
350 |
assert(_chunkwriter.is_valid(), "invariant"); |
|
351 |
_storage.control().set_to_disk(true); |
|
352 |
} |
|
353 |
||
354 |
void JfrRecorderService::in_memory_rotation() { |
|
355 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
356 |
// currently running an in-memory recording |
|
357 |
open_new_chunk(); |
|
358 |
if (_chunkwriter.is_valid()) { |
|
359 |
// dump all in-memory buffer data to the newly created chunk |
|
360 |
serialize_storage_from_in_memory_recording(); |
|
361 |
} |
|
362 |
} |
|
363 |
||
364 |
void JfrRecorderService::serialize_storage_from_in_memory_recording() { |
|
365 |
assert(!JfrStream_lock->owned_by_self(), "not holding stream lock!"); |
|
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
366 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 367 |
_storage.write(); |
368 |
} |
|
369 |
||
370 |
void JfrRecorderService::chunk_rotation() { |
|
371 |
finalize_current_chunk(); |
|
372 |
open_new_chunk(); |
|
373 |
} |
|
374 |
||
375 |
void JfrRecorderService::finalize_current_chunk() { |
|
376 |
assert(_chunkwriter.is_valid(), "invariant"); |
|
377 |
write(); |
|
378 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
379 |
} |
|
380 |
||
381 |
void JfrRecorderService::write() { |
|
382 |
ResourceMark rm; |
|
383 |
HandleMark hm; |
|
384 |
pre_safepoint_write(); |
|
385 |
invoke_safepoint_write(); |
|
386 |
post_safepoint_write(); |
|
387 |
} |
|
388 |
||
389 |
typedef ServiceFunctor<JfrStringPool, &JfrStringPool::write> WriteStringPool; |
|
390 |
typedef ServiceFunctor<JfrStringPool, &JfrStringPool::write_at_safepoint> WriteStringPoolSafepoint; |
|
391 |
typedef WriteCheckpointEvent<WriteStackTraceRepository> WriteStackTraceCheckpoint; |
|
392 |
typedef WriteCheckpointEvent<WriteStringPool> WriteStringPoolCheckpoint; |
|
393 |
typedef WriteCheckpointEvent<WriteStringPoolSafepoint> WriteStringPoolCheckpointSafepoint; |
|
394 |
||
395 |
static void write_stacktrace_checkpoint(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) { |
|
396 |
WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear); |
|
397 |
WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo); |
|
398 |
write_stack_trace_checkpoint.process(); |
|
399 |
} |
|
400 |
static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { |
|
401 |
WriteStringPool write_string_pool(string_pool); |
|
402 |
WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool); |
|
403 |
write_string_pool_checkpoint.process(); |
|
404 |
} |
|
405 |
||
406 |
static void write_stringpool_checkpoint_safepoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { |
|
407 |
WriteStringPoolSafepoint write_string_pool(string_pool); |
|
408 |
WriteStringPoolCheckpointSafepoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool); |
|
409 |
write_string_pool_checkpoint.process(); |
|
410 |
} |
|
411 |
||
412 |
// |
|
413 |
// pre-safepoint write sequence |
|
414 |
// |
|
415 |
// lock stream lock -> |
|
416 |
// write non-safepoint dependent types -> |
|
417 |
// write checkpoint epoch transition list-> |
|
418 |
// write stack trace checkpoint -> |
|
419 |
// write string pool checkpoint -> |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
420 |
// write object sample stacktraces -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
421 |
// write storage -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
422 |
// release stream lock |
50113 | 423 |
// |
424 |
void JfrRecorderService::pre_safepoint_write() { |
|
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
425 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 426 |
assert(_chunkwriter.is_valid(), "invariant"); |
427 |
_checkpoint_manager.write_types(); |
|
428 |
_checkpoint_manager.write_epoch_transition_mspace(); |
|
429 |
write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false); |
|
430 |
write_stringpool_checkpoint(_string_pool, _chunkwriter); |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
431 |
if (LeakProfiler::is_running()) { |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
432 |
// Exclusive access to the object sampler instance. |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
433 |
// The sampler is released (unlocked) later in post_safepoint_write. |
58132
caa25ab47aca
8225797: OldObjectSample event creates unexpected amount of checkpoint data
mgronlun
parents:
55571
diff
changeset
|
434 |
ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire(), _stack_trace_repository); |
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
435 |
} |
50113 | 436 |
_storage.write(); |
437 |
} |
|
438 |
||
439 |
void JfrRecorderService::invoke_safepoint_write() { |
|
440 |
JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this); |
|
441 |
VMThread::execute(&safepoint_task); |
|
442 |
} |
|
443 |
||
444 |
// |
|
445 |
// safepoint write sequence |
|
446 |
// |
|
447 |
// lock stream lock -> |
|
448 |
// write stacktrace repository -> |
|
449 |
// write string pool -> |
|
450 |
// write safepoint dependent types -> |
|
451 |
// write storage -> |
|
452 |
// shift_epoch -> |
|
453 |
// update time -> |
|
454 |
// lock metadata descriptor -> |
|
455 |
// release stream lock |
|
456 |
// |
|
457 |
void JfrRecorderService::safepoint_write() { |
|
458 |
assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
|
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
459 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 460 |
write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true); |
461 |
write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter); |
|
462 |
_checkpoint_manager.write_safepoint_types(); |
|
463 |
_storage.write_at_safepoint(); |
|
464 |
_checkpoint_manager.shift_epoch(); |
|
465 |
_chunkwriter.time_stamp_chunk_now(); |
|
466 |
JfrMetadataEvent::lock(); |
|
467 |
} |
|
468 |
||
53897
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
469 |
static int64_t write_metadata_event(JfrChunkWriter& chunkwriter) { |
50113 | 470 |
assert(chunkwriter.is_valid(), "invariant"); |
53897
0abec72a3ac2
8217647: JFR: recordings on 32-bit systems unreadable
bulasevich
parents:
53014
diff
changeset
|
471 |
const int64_t metadata_offset = chunkwriter.current_offset(); |
50113 | 472 |
JfrMetadataEvent::write(chunkwriter, metadata_offset); |
473 |
return metadata_offset; |
|
474 |
} |
|
475 |
||
476 |
// |
|
477 |
// post-safepoint write sequence |
|
478 |
// |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
479 |
// write type set -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
480 |
// release object sampler -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
481 |
// lock stream lock -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
482 |
// write checkpoints -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
483 |
// write metadata event -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
484 |
// write chunk header -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
485 |
// close chunk fd -> |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
486 |
// release stream lock |
50113 | 487 |
// |
488 |
void JfrRecorderService::post_safepoint_write() { |
|
489 |
assert(_chunkwriter.is_valid(), "invariant"); |
|
490 |
// During the safepoint tasks just completed, the system transitioned to a new epoch. |
|
491 |
// Type tagging is epoch relative which entails we are able to write out the |
|
492 |
// already tagged artifacts for the previous epoch. We can accomplish this concurrently |
|
493 |
// with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint. |
|
494 |
_checkpoint_manager.write_type_set(); |
|
55571
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
495 |
if (LeakProfiler::is_running()) { |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
496 |
// The object sampler instance was exclusively acquired and locked in pre_safepoint_write. |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
497 |
// Note: There is a dependency on write_type_set() above, ensure the release is subsequent. |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
498 |
ObjectSampler::release(); |
49102ba8cf14
8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
mgronlun
parents:
54623
diff
changeset
|
499 |
} |
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
500 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 501 |
// serialize any outstanding checkpoint memory |
502 |
_checkpoint_manager.write(); |
|
503 |
// serialize the metadata descriptor event and close out the chunk |
|
504 |
_repository.close_chunk(write_metadata_event(_chunkwriter)); |
|
505 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
506 |
} |
|
507 |
||
508 |
void JfrRecorderService::vm_error_rotation() { |
|
509 |
if (_chunkwriter.is_valid()) { |
|
510 |
finalize_current_chunk_on_vm_error(); |
|
511 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
512 |
_repository.on_vm_error(); |
|
513 |
} |
|
514 |
} |
|
515 |
||
516 |
void JfrRecorderService::finalize_current_chunk_on_vm_error() { |
|
517 |
assert(_chunkwriter.is_valid(), "invariant"); |
|
518 |
pre_safepoint_write(); |
|
519 |
// Do not attempt safepoint dependent operations during emergency dump. |
|
520 |
// Optimistically write tagged artifacts. |
|
521 |
_checkpoint_manager.shift_epoch(); |
|
522 |
// update time |
|
523 |
_chunkwriter.time_stamp_chunk_now(); |
|
524 |
post_safepoint_write(); |
|
525 |
assert(!_chunkwriter.is_valid(), "invariant"); |
|
526 |
} |
|
527 |
||
528 |
void JfrRecorderService::process_full_buffers() { |
|
529 |
if (_chunkwriter.is_valid()) { |
|
530 |
assert(!JfrStream_lock->owned_by_self(), "invariant"); |
|
54623
1126f0607c70
8222811: Consolidate MutexLockerEx and MutexLocker
coleenp
parents:
53897
diff
changeset
|
531 |
MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
50113 | 532 |
_storage.write_full(); |
533 |
} |
|
534 |
} |
|
535 |
||
536 |
void JfrRecorderService::scavenge() { |
|
537 |
_storage.scavenge(); |
|
538 |
} |
|
539 |
||
540 |
void JfrRecorderService::evaluate_chunk_size_for_rotation() { |
|
53014
339d2fbe8675
8215284: Reduce noise induced by periodic task getFileSize()
mgronlun
parents:
52877
diff
changeset
|
541 |
JfrChunkRotation::evaluate(_chunkwriter); |
50113 | 542 |
} |