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