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