src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
branchJEP-349-branch
changeset 58823 6a21dba79b81
parent 58578 7b89c53db169
equal deleted inserted replaced
58806:a7d850b47b19 58823:6a21dba79b81
    54 #include "runtime/safepoint.hpp"
    54 #include "runtime/safepoint.hpp"
    55 #include "runtime/thread.inline.hpp"
    55 #include "runtime/thread.inline.hpp"
    56 #include "runtime/vmOperations.hpp"
    56 #include "runtime/vmOperations.hpp"
    57 #include "runtime/vmThread.hpp"
    57 #include "runtime/vmThread.hpp"
    58 
    58 
    59 // set data iff *dest == NULL
       
    60 static bool try_set(void* const data, void** dest, bool clear) {
       
    61   assert(data != NULL, "invariant");
       
    62   const void* const current = *dest;
       
    63   if (current != NULL) {
       
    64     if (current != data) {
       
    65       // already set
       
    66       return false;
       
    67     }
       
    68     assert(current == data, "invariant");
       
    69     if (!clear) {
       
    70       // recursion disallowed
       
    71       return false;
       
    72     }
       
    73   }
       
    74   return Atomic::cmpxchg(clear ? NULL : data, dest, current) == current;
       
    75 }
       
    76 
       
    77 static void* rotation_thread = NULL;
       
    78 static const int rotation_try_limit = 1000;
       
    79 static const int rotation_retry_sleep_millis = 10;
       
    80 
       
    81 // incremented on each flushpoint
    59 // incremented on each flushpoint
    82 static u8 flushpoint_id = 0;
    60 static u8 flushpoint_id = 0;
    83 
       
    84 class RotationLock : public StackObj {
       
    85  private:
       
    86   Thread* const _thread;
       
    87   bool _acquired;
       
    88 
       
    89   void log(bool recursion) {
       
    90     assert(!_acquired, "invariant");
       
    91     const char* error_msg = NULL;
       
    92     if (recursion) {
       
    93       error_msg = "Unable to issue rotation due to recursive calls.";
       
    94     }
       
    95     else {
       
    96       error_msg = "Unable to issue rotation due to wait timeout.";
       
    97     }
       
    98     log_info(jfr)( // For user, should not be "jfr, system"
       
    99       "%s", error_msg);
       
   100   }
       
   101  public:
       
   102   RotationLock(Thread* thread) : _thread(thread), _acquired(false) {
       
   103     assert(_thread != NULL, "invariant");
       
   104     if (_thread == rotation_thread) {
       
   105       // recursion not supported
       
   106       log(true);
       
   107       return;
       
   108     }
       
   109 
       
   110     // limited to not spin indefinitely
       
   111     for (int i = 0; i < rotation_try_limit; ++i) {
       
   112       if (try_set(_thread, &rotation_thread, false)) {
       
   113         _acquired = true;
       
   114         assert(_thread == rotation_thread, "invariant");
       
   115         return;
       
   116       }
       
   117       if (_thread->is_Java_thread()) {
       
   118         // in order to allow the system to move to a safepoint
       
   119         MutexLocker msg_lock(JfrMsg_lock);
       
   120         JfrMsg_lock->wait(rotation_retry_sleep_millis);
       
   121       }
       
   122       else {
       
   123         os::naked_short_sleep(rotation_retry_sleep_millis);
       
   124       }
       
   125     }
       
   126     log(false);
       
   127   }
       
   128 
       
   129   ~RotationLock() {
       
   130     assert(_thread != NULL, "invariant");
       
   131     if (_acquired) {
       
   132       assert(_thread == rotation_thread, "invariant");
       
   133       while (!try_set(_thread, &rotation_thread, true));
       
   134     }
       
   135   }
       
   136   bool not_acquired() const { return !_acquired; }
       
   137 };
       
   138 
    61 
   139 template <typename E, typename Instance, size_t(Instance::*func)()>
    62 template <typename E, typename Instance, size_t(Instance::*func)()>
   140 class Content {
    63 class Content {
   141  private:
    64  private:
   142   Instance& _instance;
    65   Instance& _instance;
   436 bool JfrRecorderService::is_recording() {
   359 bool JfrRecorderService::is_recording() {
   437   return recording;
   360   return recording;
   438 }
   361 }
   439 
   362 
   440 void JfrRecorderService::start() {
   363 void JfrRecorderService::start() {
   441   RotationLock rl(Thread::current());
   364   MutexLocker lock(JfrStream_lock);
   442   if (rl.not_acquired()) {
       
   443     return;
       
   444   }
       
   445   log_debug(jfr, system)("Request to START recording");
   365   log_debug(jfr, system)("Request to START recording");
   446   assert(!is_recording(), "invariant");
   366   assert(!is_recording(), "invariant");
   447   clear();
   367   clear();
   448   set_recording_state(true);
   368   set_recording_state(true);
   449   assert(is_recording(), "invariant");
   369   assert(is_recording(), "invariant");
   458   invoke_safepoint_clear();
   378   invoke_safepoint_clear();
   459   post_safepoint_clear();
   379   post_safepoint_clear();
   460 }
   380 }
   461 
   381 
   462 void JfrRecorderService::pre_safepoint_clear() {
   382 void JfrRecorderService::pre_safepoint_clear() {
   463   _stack_trace_repository.clear();
       
   464   _string_pool.clear();
   383   _string_pool.clear();
   465   _storage.clear();
   384   _storage.clear();
       
   385   _stack_trace_repository.clear();
   466 }
   386 }
   467 
   387 
   468 void JfrRecorderService::invoke_safepoint_clear() {
   388 void JfrRecorderService::invoke_safepoint_clear() {
   469   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_clear> safepoint_task(*this);
   389   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_clear> safepoint_task(*this);
   470   VMThread::execute(&safepoint_task);
   390   VMThread::execute(&safepoint_task);
   471 }
   391 }
   472 
   392 
   473 void JfrRecorderService::safepoint_clear() {
   393 void JfrRecorderService::safepoint_clear() {
   474   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   394   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   475   _stack_trace_repository.clear();
       
   476   _string_pool.clear();
   395   _string_pool.clear();
   477   _storage.clear();
   396   _storage.clear();
   478   _checkpoint_manager.shift_epoch();
   397   _checkpoint_manager.shift_epoch();
   479   _chunkwriter.set_time_stamp();
   398   _chunkwriter.set_time_stamp();
       
   399   _stack_trace_repository.clear();
   480 }
   400 }
   481 
   401 
   482 void JfrRecorderService::post_safepoint_clear() {
   402 void JfrRecorderService::post_safepoint_clear() {
   483   _checkpoint_manager.clear();
   403   _checkpoint_manager.clear();
   484 }
   404 }
   498   set_recording_state(false);
   418   set_recording_state(false);
   499   assert(!JfrRecorderService::is_recording(), "invariant");
   419   assert(!JfrRecorderService::is_recording(), "invariant");
   500 }
   420 }
   501 
   421 
   502 void JfrRecorderService::prepare_for_vm_error_rotation() {
   422 void JfrRecorderService::prepare_for_vm_error_rotation() {
       
   423   assert(JfrStream_lock->owned_by_self(), "invariant");
   503   if (!_chunkwriter.is_valid()) {
   424   if (!_chunkwriter.is_valid()) {
   504     open_new_chunk(true);
   425     open_new_chunk(true);
   505   }
   426   }
   506   _checkpoint_manager.register_service_thread(Thread::current());
   427   _checkpoint_manager.register_service_thread(Thread::current());
   507 }
   428 }
   508 
   429 
   509 void JfrRecorderService::vm_error_rotation() {
   430 void JfrRecorderService::vm_error_rotation() {
       
   431   assert(JfrStream_lock->owned_by_self(), "invariant");
   510   if (_chunkwriter.is_valid()) {
   432   if (_chunkwriter.is_valid()) {
   511     Thread* const t = Thread::current();
   433     Thread* const t = Thread::current();
   512     _storage.flush_regular_buffer(t->jfr_thread_local()->native_buffer(), t);
   434     _storage.flush_regular_buffer(t->jfr_thread_local()->native_buffer(), t);
   513     invoke_flush(t);
   435     invoke_flush();
   514     _chunkwriter.set_time_stamp();
   436     _chunkwriter.set_time_stamp();
   515     _repository.close_chunk();
   437     _repository.close_chunk();
   516     assert(!_chunkwriter.is_valid(), "invariant");
   438     assert(!_chunkwriter.is_valid(), "invariant");
   517     _repository.on_vm_error();
   439     _repository.on_vm_error();
   518   }
   440   }
   519 }
   441 }
   520 
   442 
   521 void JfrRecorderService::rotate(int msgs) {
   443 void JfrRecorderService::rotate(int msgs) {
   522   RotationLock rl(Thread::current());
   444   assert(!JfrStream_lock->owned_by_self(), "invariant");
   523   if (rl.not_acquired()) {
   445   MutexLocker lock(JfrStream_lock);
   524     return;
       
   525   }
       
   526   static bool vm_error = false;
   446   static bool vm_error = false;
   527   if (msgs & MSGBIT(MSG_VM_ERROR)) {
   447   if (msgs & MSGBIT(MSG_VM_ERROR)) {
   528     vm_error = true;
   448     vm_error = true;
   529     prepare_for_vm_error_rotation();
   449     prepare_for_vm_error_rotation();
   530   }
   450   }
   539     stop();
   459     stop();
   540   }
   460   }
   541 }
   461 }
   542 
   462 
   543 void JfrRecorderService::in_memory_rotation() {
   463 void JfrRecorderService::in_memory_rotation() {
       
   464   assert(JfrStream_lock->owned_by_self(), "invariant");
   544   // currently running an in-memory recording
   465   // currently running an in-memory recording
   545   assert(!_storage.control().to_disk(), "invariant");
   466   assert(!_storage.control().to_disk(), "invariant");
   546   open_new_chunk();
   467   open_new_chunk();
   547   if (_chunkwriter.is_valid()) {
   468   if (_chunkwriter.is_valid()) {
   548     // dump all in-memory buffer data to the newly created chunk
   469     // dump all in-memory buffer data to the newly created chunk
   549     write_storage(_storage, _chunkwriter);
   470     write_storage(_storage, _chunkwriter);
   550   }
   471   }
   551 }
   472 }
   552 
   473 
   553 void JfrRecorderService::chunk_rotation() {
   474 void JfrRecorderService::chunk_rotation() {
       
   475   assert(JfrStream_lock->owned_by_self(), "invariant");
   554   finalize_current_chunk();
   476   finalize_current_chunk();
   555   open_new_chunk();
   477   open_new_chunk();
   556 }
   478 }
   557 
   479 
   558 void JfrRecorderService::finalize_current_chunk() {
   480 void JfrRecorderService::finalize_current_chunk() {
   568   post_safepoint_write();
   490   post_safepoint_write();
   569 }
   491 }
   570 
   492 
   571 void JfrRecorderService::pre_safepoint_write() {
   493 void JfrRecorderService::pre_safepoint_write() {
   572   assert(_chunkwriter.is_valid(), "invariant");
   494   assert(_chunkwriter.is_valid(), "invariant");
   573   if (_stack_trace_repository.is_modified()) {
       
   574     write_stacktrace(_stack_trace_repository, _chunkwriter, false);
       
   575   }
       
   576   if (_string_pool.is_modified()) {
       
   577     write_stringpool(_string_pool, _chunkwriter);
       
   578   }
       
   579   if (LeakProfiler::is_running()) {
   495   if (LeakProfiler::is_running()) {
   580     // Exclusive access to the object sampler instance.
   496     // Exclusive access to the object sampler instance.
   581     // The sampler is released (unlocked) later in post_safepoint_write.
   497     // The sampler is released (unlocked) later in post_safepoint_write.
   582     ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire(), _stack_trace_repository);
   498     ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire(), _stack_trace_repository);
   583   }
   499   }
       
   500   if (_string_pool.is_modified()) {
       
   501     write_stringpool(_string_pool, _chunkwriter);
       
   502   }
   584   write_storage(_storage, _chunkwriter);
   503   write_storage(_storage, _chunkwriter);
       
   504   if (_stack_trace_repository.is_modified()) {
       
   505     write_stacktrace(_stack_trace_repository, _chunkwriter, false);
       
   506   }
   585 }
   507 }
   586 
   508 
   587 void JfrRecorderService::invoke_safepoint_write() {
   509 void JfrRecorderService::invoke_safepoint_write() {
   588   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
   510   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
   589   VMThread::execute(&safepoint_task);
   511   VMThread::execute(&safepoint_task);
   590 }
   512 }
   591 
   513 
   592 void JfrRecorderService::safepoint_write() {
   514 void JfrRecorderService::safepoint_write() {
   593   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   515   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   594   write_stacktrace(_stack_trace_repository, _chunkwriter, true);
       
   595   if (_string_pool.is_modified()) {
   516   if (_string_pool.is_modified()) {
   596     write_stringpool_safepoint(_string_pool, _chunkwriter);
   517     write_stringpool_safepoint(_string_pool, _chunkwriter);
   597   }
   518   }
       
   519   _checkpoint_manager.on_rotation();
   598   _storage.write_at_safepoint();
   520   _storage.write_at_safepoint();
   599   _checkpoint_manager.on_rotation();
   521   _checkpoint_manager.shift_epoch();
   600   _chunkwriter.set_time_stamp();
   522   _chunkwriter.set_time_stamp();
       
   523   write_stacktrace(_stack_trace_repository, _chunkwriter, true);
   601 }
   524 }
   602 
   525 
   603 void JfrRecorderService::post_safepoint_write() {
   526 void JfrRecorderService::post_safepoint_write() {
   604   assert(_chunkwriter.is_valid(), "invariant");
   527   assert(_chunkwriter.is_valid(), "invariant");
   605   // During the safepoint tasks just completed, the system transitioned to a new epoch.
   528   // During the safepoint tasks just completed, the system transitioned to a new epoch.
   641     reset_buffer(buffer, t);
   564     reset_buffer(buffer, t);
   642   }
   565   }
   643 }
   566 }
   644 
   567 
   645 size_t JfrRecorderService::flush() {
   568 size_t JfrRecorderService::flush() {
       
   569   assert(JfrStream_lock->owned_by_self(), "invariant");
   646   size_t total_elements = flush_metadata(_chunkwriter);
   570   size_t total_elements = flush_metadata(_chunkwriter);
   647   const size_t storage_elements = flush_storage(_storage, _chunkwriter);
   571   const size_t storage_elements = flush_storage(_storage, _chunkwriter);
   648   if (0 == storage_elements) {
   572   if (0 == storage_elements) {
   649     return total_elements;
   573     return total_elements;
   650   }
   574   }
   651   total_elements += storage_elements;
   575   total_elements += storage_elements;
       
   576   if (_string_pool.is_modified()) {
       
   577     total_elements += flush_stringpool(_string_pool, _chunkwriter);
       
   578   }
   652   if (_stack_trace_repository.is_modified()) {
   579   if (_stack_trace_repository.is_modified()) {
   653     total_elements += flush_stacktrace(_stack_trace_repository, _chunkwriter);
   580     total_elements += flush_stacktrace(_stack_trace_repository, _chunkwriter);
   654   }
       
   655   if (_string_pool.is_modified()) {
       
   656     total_elements += flush_stringpool(_string_pool, _chunkwriter);
       
   657   }
   581   }
   658   if (_checkpoint_manager.is_type_set_required()) {
   582   if (_checkpoint_manager.is_type_set_required()) {
   659     total_elements += flush_typeset(_checkpoint_manager, _chunkwriter);
   583     total_elements += flush_typeset(_checkpoint_manager, _chunkwriter);
   660   } else if (_checkpoint_manager.is_static_type_set_required()) {
   584   } else if (_checkpoint_manager.is_static_type_set_required()) {
   661     // don't tally this, it is only in order to flush the waiting constants
   585     // don't tally this, it is only in order to flush the waiting constants
   665 }
   589 }
   666 
   590 
   667 typedef Content<EventFlush, JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
   591 typedef Content<EventFlush, JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
   668 typedef WriteContent<FlushFunctor> Flush;
   592 typedef WriteContent<FlushFunctor> Flush;
   669 
   593 
   670 void JfrRecorderService::invoke_flush(Thread* t) {
   594 void JfrRecorderService::invoke_flush() {
   671   assert(t != NULL, "invariant");
   595   assert(JfrStream_lock->owned_by_self(), "invariant");
   672   assert(_chunkwriter.is_valid(), "invariant");
   596   assert(_chunkwriter.is_valid(), "invariant");
       
   597   Thread* const t = Thread::current();
   673   ResourceMark rm(t);
   598   ResourceMark rm(t);
   674   HandleMark hm(t);
   599   HandleMark hm(t);
   675   ++flushpoint_id;
   600   ++flushpoint_id;
   676   reset_thread_local_buffer(t);
   601   reset_thread_local_buffer(t);
   677   FlushFunctor flushpoint(*this);
   602   FlushFunctor flushpoint(*this);
   680   write_thread_local_buffer(_chunkwriter, t);
   605   write_thread_local_buffer(_chunkwriter, t);
   681   _repository.flush_chunk();
   606   _repository.flush_chunk();
   682 }
   607 }
   683 
   608 
   684 void JfrRecorderService::flushpoint() {
   609 void JfrRecorderService::flushpoint() {
   685   Thread* const t = Thread::current();
   610   MutexLocker lock(JfrStream_lock);
   686   RotationLock rl(t);
   611   invoke_flush();
   687   if (rl.not_acquired() || !_chunkwriter.is_valid()) {
       
   688     return;
       
   689   }
       
   690   invoke_flush(t);
       
   691 }
   612 }
   692 
   613 
   693 void JfrRecorderService::process_full_buffers() {
   614 void JfrRecorderService::process_full_buffers() {
   694   if (_chunkwriter.is_valid()) {
   615   if (_chunkwriter.is_valid()) {
   695     _storage.write_full();
   616     _storage.write_full();