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