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/jfrTraceTime.hpp"
  42 #include "jfr/writers/jfrJavaEventWriter.hpp"
  43 #include "logging/log.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.inline.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 #include "tracefiles/traceTypes.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 constant_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(JfrTraceTime::now().value());
 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 constant types in this checkpoint
 143   cw.write<u8>(constant_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 _constant_type_id;
 154   ContentFunctor& _content_functor;
 155  public:
 156   WriteCheckpointEvent(JfrChunkWriter& cw, u8 constant_type_id, ContentFunctor& functor) :
 157     _cw(cw),
 158     _constant_type_id(constant_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, _constant_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 WriteCheckpointEvent<WriteStackTraceRepository> WriteStackTraceCheckpoint;
 390 typedef WriteCheckpointEvent<WriteStringPool> WriteStringPoolCheckpoint;
 391 
 392 static void write_stacktrace_checkpoint(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) {
 393   WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear);
 394   WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, CONSTANT_TYPE_STACKTRACE, write_stacktrace_repo);
 395   write_stack_trace_checkpoint.process();
 396 }
 397 
 398 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
 399   WriteStringPool write_string_pool(string_pool);
 400   WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, CONSTANT_TYPE_STRING, write_string_pool);
 401   write_string_pool_checkpoint.process();
 402 }
 403 
 404 //
 405 // pre-safepoint write sequence
 406 //
 407 //  lock stream lock ->
 408 //    write constant types ->
 409 //      write checkpoint epoch transition list->
 410 //        write stack trace checkpoint ->
 411 //          write string pool checkpoint ->
 412 //            write storage ->
 413 //              release stream lock
 414 //
 415 void JfrRecorderService::pre_safepoint_write() {
 416   MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
 417   assert(_chunkwriter.is_valid(), "invariant");
 418   _checkpoint_manager.write_constant_types();
 419   _checkpoint_manager.write_epoch_transition_list();
 420   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
 421   write_stringpool_checkpoint(_string_pool, _chunkwriter);
 422   _storage.write();
 423 }
 424 
 425 void JfrRecorderService::invoke_safepoint_write() {
 426   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
 427   VMThread::execute(&safepoint_task);
 428 }
 429 
 430 static void write_object_sample_stacktrace(JfrStackTraceRepository& stack_trace_repository) {
 431   WriteObjectSampleStacktrace object_sample_stacktrace(stack_trace_repository);
 432   object_sample_stacktrace.process();
 433 }
 434 
 435 //
 436 // safepoint write sequence
 437 //
 438 //   lock stream lock ->
 439 //     write object sample stacktraces ->
 440 //       write stacktrace repository ->
 441 //         write string pool ->
 442 //           write safepoint dependent constant types ->
 443 //             write storage ->
 444 //                 shift_epoch ->
 445 //                   update time ->
 446 //                     lock metadata descriptor ->
 447 //                       release stream lock
 448 //
 449 void JfrRecorderService::safepoint_write() {
 450   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
 451   MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
 452   write_object_sample_stacktrace(_stack_trace_repository);
 453   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
 454   write_stringpool_checkpoint(_string_pool, _chunkwriter);
 455   _checkpoint_manager.write_safepoint_constant_types();
 456   _storage.write_at_safepoint();
 457   _checkpoint_manager.shift_epoch();
 458   _chunkwriter.time_stamp_chunk_now();
 459   JfrMetadataEvent::lock();
 460 }
 461 
 462 static jlong write_metadata_event(JfrChunkWriter& chunkwriter) {
 463   assert(chunkwriter.is_valid(), "invariant");
 464   const jlong metadata_offset = chunkwriter.current_offset();
 465   JfrMetadataEvent::write(chunkwriter, metadata_offset);
 466   return metadata_offset;
 467 }
 468 
 469 //
 470 // post-safepoint write sequence
 471 //
 472 //  lock stream lock ->
 473 //    write constant tag set ->
 474 //      write checkpoints ->
 475 //        write metadata event ->
 476 //          write chunk header ->
 477 //            close chunk fd ->
 478 //              release stream lock
 479 //
 480 void JfrRecorderService::post_safepoint_write() {
 481   assert(_chunkwriter.is_valid(), "invariant");
 482   // During the safepoint tasks just completed, the system transitioned to a new epoch.
 483   // Constant tagging is epoch relative which entails we are able to write out the
 484   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
 485   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
 486   _checkpoint_manager.write_constant_tag_set();
 487   MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
 488   // serialize any outstanding checkpoint memory
 489   _checkpoint_manager.write();
 490   // serialize the metadata descriptor event and close out the chunk
 491   _repository.close_chunk(write_metadata_event(_chunkwriter));
 492   assert(!_chunkwriter.is_valid(), "invariant");
 493 }
 494 
 495 void JfrRecorderService::vm_error_rotation() {
 496   if (_chunkwriter.is_valid()) {
 497     finalize_current_chunk_on_vm_error();
 498     assert(!_chunkwriter.is_valid(), "invariant");
 499     _repository.on_vm_error();
 500   }
 501 }
 502 
 503 void JfrRecorderService::finalize_current_chunk_on_vm_error() {
 504   assert(_chunkwriter.is_valid(), "invariant");
 505   pre_safepoint_write();
 506   JfrMetadataEvent::lock();
 507   // Do not attempt safepoint dependent operations during emergency dump.
 508   // Optimistically write tagged constant artifacts.
 509   _checkpoint_manager.shift_epoch();
 510   _checkpoint_manager.write_constant_tag_set();
 511   // update time
 512   _chunkwriter.time_stamp_chunk_now();
 513   post_safepoint_write();
 514   assert(!_chunkwriter.is_valid(), "invariant");
 515 }
 516 
 517 void JfrRecorderService::process_full_buffers() {
 518   if (_chunkwriter.is_valid()) {
 519     assert(!JfrStream_lock->owned_by_self(), "invariant");
 520     MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
 521     _storage.write_full();
 522   }
 523 }
 524 
 525 void JfrRecorderService::scavenge() {
 526   _storage.scavenge();
 527 }
 528 
 529 void JfrRecorderService::evaluate_chunk_size_for_rotation() {
 530   const size_t size_written = _chunkwriter.size_written();
 531   if (size_written > JfrChunkSizeNotifier::chunk_size_threshold()) {
 532     JfrChunkSizeNotifier::notify();
 533   }
 534 }