src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54964 ec7d6d8effc7
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    35 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
    35 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
    36 #include "jfr/utilities/jfrBigEndian.hpp"
    36 #include "jfr/utilities/jfrBigEndian.hpp"
    37 #include "jfr/utilities/jfrTypes.hpp"
    37 #include "jfr/utilities/jfrTypes.hpp"
    38 #include "logging/log.hpp"
    38 #include "logging/log.hpp"
    39 #include "memory/resourceArea.hpp"
    39 #include "memory/resourceArea.hpp"
       
    40 #include "runtime/handles.inline.hpp"
    40 #include "runtime/mutexLocker.hpp"
    41 #include "runtime/mutexLocker.hpp"
    41 #include "runtime/orderAccess.hpp"
    42 #include "runtime/orderAccess.hpp"
    42 #include "runtime/os.inline.hpp"
    43 #include "runtime/os.inline.hpp"
    43 #include "runtime/safepoint.hpp"
    44 #include "runtime/safepoint.hpp"
    44 
    45 
    85 
    86 
    86 static const size_t unlimited_mspace_size = 0;
    87 static const size_t unlimited_mspace_size = 0;
    87 static const size_t checkpoint_buffer_cache_count = 2;
    88 static const size_t checkpoint_buffer_cache_count = 2;
    88 static const size_t checkpoint_buffer_size = 512 * K;
    89 static const size_t checkpoint_buffer_size = 512 * K;
    89 
    90 
    90 static JfrCheckpointMspace* create_mspace(size_t buffer_size, size_t limit, size_t cache_count, JfrCheckpointManager* system) {
    91 static JfrCheckpointMspace* allocate_mspace(size_t size, size_t limit, size_t cache_count, JfrCheckpointManager* mgr) {
    91   JfrCheckpointMspace* mspace = new JfrCheckpointMspace(buffer_size, limit, cache_count, system);
    92   return create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(size, limit, cache_count, mgr);
    92   if (mspace != NULL) {
       
    93     mspace->initialize();
       
    94   }
       
    95   return mspace;
       
    96 }
    93 }
    97 
    94 
    98 bool JfrCheckpointManager::initialize() {
    95 bool JfrCheckpointManager::initialize() {
    99   assert(_free_list_mspace == NULL, "invariant");
    96   assert(_free_list_mspace == NULL, "invariant");
   100   _free_list_mspace = create_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
    97   _free_list_mspace = allocate_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
   101   if (_free_list_mspace == NULL) {
    98   if (_free_list_mspace == NULL) {
   102     return false;
    99     return false;
   103   }
   100   }
   104   assert(_epoch_transition_mspace == NULL, "invariant");
   101   assert(_epoch_transition_mspace == NULL, "invariant");
   105   _epoch_transition_mspace = create_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
   102   _epoch_transition_mspace = allocate_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
   106   if (_epoch_transition_mspace == NULL) {
   103   if (_epoch_transition_mspace == NULL) {
   107     return false;
   104     return false;
   108   }
   105   }
   109   assert(_lock == NULL, "invariant");
   106   assert(_lock == NULL, "invariant");
   110   _lock = new Mutex(Monitor::leaf - 1, "Checkpoint mutex", Mutex::_allow_vm_block_flag, Monitor::_safepoint_check_never);
   107   _lock = new Mutex(Monitor::leaf - 1, "Checkpoint mutex", Mutex::_allow_vm_block_flag, Monitor::_safepoint_check_never);
   111   if (_lock == NULL) {
   108   if (_lock == NULL) {
   112     return false;
   109     return false;
   113   }
   110   }
   114   return JfrTypeManager::initialize();
   111   return JfrTypeManager::initialize();
   115 }
       
   116 
       
   117 bool JfrCheckpointManager::use_epoch_transition_mspace(const Thread* thread) const {
       
   118   return _service_thread != thread && OrderAccess::load_acquire(&_checkpoint_epoch_state) != JfrTraceIdEpoch::epoch();
       
   119 }
       
   120 
       
   121 void JfrCheckpointManager::synchronize_epoch() {
       
   122   assert(_checkpoint_epoch_state != JfrTraceIdEpoch::epoch(), "invariant");
       
   123   OrderAccess::storestore();
       
   124   _checkpoint_epoch_state = JfrTraceIdEpoch::epoch();
       
   125 }
       
   126 
       
   127 void JfrCheckpointManager::shift_epoch() {
       
   128   debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
       
   129   JfrTraceIdEpoch::shift_epoch();
       
   130   assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
       
   131 }
   112 }
   132 
   113 
   133 void JfrCheckpointManager::register_service_thread(const Thread* thread) {
   114 void JfrCheckpointManager::register_service_thread(const Thread* thread) {
   134   _service_thread = thread;
   115   _service_thread = thread;
   135 }
   116 }
   149 void JfrCheckpointManager::unlock() {
   130 void JfrCheckpointManager::unlock() {
   150   _lock->unlock();
   131   _lock->unlock();
   151 }
   132 }
   152 
   133 
   153 #ifdef ASSERT
   134 #ifdef ASSERT
   154 
       
   155 bool JfrCheckpointManager::is_locked() const {
   135 bool JfrCheckpointManager::is_locked() const {
   156   return _lock->owned_by_self();
   136   return _lock->owned_by_self();
   157 }
   137 }
   158 
   138 
   159 static void assert_free_lease(const BufferPtr buffer) {
   139 static void assert_free_lease(const BufferPtr buffer) {
   165 static void assert_release(const BufferPtr buffer) {
   145 static void assert_release(const BufferPtr buffer) {
   166   assert(buffer != NULL, "invariant");
   146   assert(buffer != NULL, "invariant");
   167   assert(buffer->lease(), "invariant");
   147   assert(buffer->lease(), "invariant");
   168   assert(buffer->acquired_by_self(), "invariant");
   148   assert(buffer->acquired_by_self(), "invariant");
   169 }
   149 }
   170 
       
   171 #endif // ASSERT
   150 #endif // ASSERT
   172 
   151 
   173 static BufferPtr lease_free(size_t size, JfrCheckpointMspace* mspace, size_t retry_count, Thread* thread) {
   152 static BufferPtr lease_free(size_t size, JfrCheckpointMspace* mspace, size_t retry_count, Thread* thread) {
   174   static const size_t max_elem_size = mspace->min_elem_size(); // min is max
   153   static const size_t max_elem_size = mspace->min_elem_size(); // min is max
   175   BufferPtr buffer;
   154   BufferPtr buffer;
   181     }
   160     }
   182   }
   161   }
   183   buffer = mspace_allocate_transient_lease_to_free(size, mspace, thread);
   162   buffer = mspace_allocate_transient_lease_to_free(size, mspace, thread);
   184   DEBUG_ONLY(assert_free_lease(buffer);)
   163   DEBUG_ONLY(assert_free_lease(buffer);)
   185   return buffer;
   164   return buffer;
       
   165 }
       
   166 
       
   167 bool JfrCheckpointManager::use_epoch_transition_mspace(const Thread* thread) const {
       
   168   return _service_thread != thread && OrderAccess::load_acquire(&_checkpoint_epoch_state) != JfrTraceIdEpoch::epoch();
   186 }
   169 }
   187 
   170 
   188 static const size_t lease_retry = 10;
   171 static const size_t lease_retry = 10;
   189 
   172 
   190 BufferPtr JfrCheckpointManager::lease_buffer(Thread* thread, size_t size /* 0 */) {
   173 BufferPtr JfrCheckpointManager::lease_buffer(Thread* thread, size_t size /* 0 */) {
   254 
   237 
   255 static juint number_of_types(const u1* data) {
   238 static juint number_of_types(const u1* data) {
   256   return read_data<juint>(data + types_offset);
   239   return read_data<juint>(data + types_offset);
   257 }
   240 }
   258 
   241 
   259 static void write_checkpoint_header(JfrChunkWriter& cw, intptr_t offset_prev_cp_event, const u1* data) {
   242 static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) {
   260   cw.reserve(sizeof(u4));
   243   cw.reserve(sizeof(u4));
   261   cw.write((u8)EVENT_CHECKPOINT);
   244   cw.write<u8>(EVENT_CHECKPOINT);
   262   cw.write(starttime(data));
   245   cw.write(starttime(data));
   263   cw.write(duration(data));
   246   cw.write(duration(data));
   264   cw.write((jlong)offset_prev_cp_event);
   247   cw.write(offset_prev_cp_event);
   265   cw.write(is_flushpoint(data));
   248   cw.write(is_flushpoint(data));
   266   cw.write(number_of_types(data));
   249   cw.write(number_of_types(data));
   267 }
   250 }
   268 
   251 
   269 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
   252 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
   270   assert(data != NULL, "invariant");
   253   assert(data != NULL, "invariant");
   271   cw.write_unbuffered(data + payload_offset, size);
   254   cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry));
   272 }
   255 }
   273 
   256 
   274 static size_t write_checkpoint_event(JfrChunkWriter& cw, const u1* data) {
   257 static size_t write_checkpoint_event(JfrChunkWriter& cw, const u1* data) {
   275   assert(data != NULL, "invariant");
   258   assert(data != NULL, "invariant");
   276   const intptr_t previous_checkpoint_event = cw.previous_checkpoint_offset();
   259   const int64_t event_begin = cw.current_offset();
   277   const intptr_t event_begin = cw.current_offset();
   260   const int64_t last_checkpoint_event = cw.last_checkpoint_offset();
   278   const intptr_t offset_to_previous_checkpoint_event = 0 == previous_checkpoint_event ? 0 : previous_checkpoint_event - event_begin;
   261   const int64_t delta = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin;
   279   const jlong total_checkpoint_size = total_size(data);
   262   const int64_t checkpoint_size = total_size(data);
   280   write_checkpoint_header(cw, offset_to_previous_checkpoint_event, data);
   263   write_checkpoint_header(cw, delta, data);
   281   write_checkpoint_content(cw, data, total_checkpoint_size - sizeof(JfrCheckpointEntry));
   264   write_checkpoint_content(cw, data, checkpoint_size);
   282   const jlong checkpoint_event_size = cw.current_offset() - event_begin;
   265   const int64_t event_size = cw.current_offset() - event_begin;
   283   cw.write_padded_at_offset<u4>(checkpoint_event_size, event_begin);
   266   cw.write_padded_at_offset<u4>(event_size, event_begin);
   284   cw.set_previous_checkpoint_offset(event_begin);
   267   cw.set_last_checkpoint_offset(event_begin);
   285   return (size_t)total_checkpoint_size;
   268   return (size_t)checkpoint_size;
   286 }
   269 }
   287 
   270 
   288 static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) {
   271 static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) {
   289   assert(cw.is_valid(), "invariant");
   272   assert(cw.is_valid(), "invariant");
   290   assert(data != NULL, "invariant");
   273   assert(data != NULL, "invariant");
   291   assert(size > 0, "invariant");
   274   assert(size > 0, "invariant");
   292   const u1* const limit = data + size;
   275   const u1* const limit = data + size;
   293   const u1* next_entry = data;
   276   const u1* next = data;
   294   size_t processed = 0;
   277   size_t processed = 0;
   295   while (next_entry < limit) {
   278   while (next < limit) {
   296     const size_t checkpoint_size = write_checkpoint_event(cw, next_entry);
   279     const size_t checkpoint_size = write_checkpoint_event(cw, next);
   297     processed += checkpoint_size;
   280     processed += checkpoint_size;
   298     next_entry += checkpoint_size;
   281     next += checkpoint_size;
   299   }
   282   }
   300   assert(next_entry == limit, "invariant");
   283   assert(next == limit, "invariant");
   301   return processed;
   284   return processed;
   302 }
   285 }
   303 
   286 
   304 template <typename T>
   287 template <typename T>
   305 class CheckpointWriteOp {
   288 class CheckpointWriteOp {
   315   }
   298   }
   316   size_t processed() const { return _processed; }
   299   size_t processed() const { return _processed; }
   317 };
   300 };
   318 
   301 
   319 typedef CheckpointWriteOp<JfrCheckpointMspace::Type> WriteOperation;
   302 typedef CheckpointWriteOp<JfrCheckpointMspace::Type> WriteOperation;
   320 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
       
   321 typedef ReleaseOp<JfrCheckpointMspace> CheckpointReleaseOperation;
   303 typedef ReleaseOp<JfrCheckpointMspace> CheckpointReleaseOperation;
   322 typedef CompositeOperation<MutexedWriteOperation, CheckpointReleaseOperation> CheckpointWriteOperation;
   304 
   323 
   305 template <template <typename> class WriterHost, template <typename, typename> class CompositeOperation>
   324 static size_t write_mspace_exclusive(JfrCheckpointMspace* mspace, JfrChunkWriter& chunkwriter) {
   306 static size_t write_mspace(JfrCheckpointMspace* mspace, JfrChunkWriter& chunkwriter) {
   325   Thread* const thread = Thread::current();
   307   assert(mspace != NULL, "invariant");
   326   WriteOperation wo(chunkwriter);
   308   WriteOperation wo(chunkwriter);
   327   MutexedWriteOperation mwo(wo);
   309   WriterHost<WriteOperation> wh(wo);
   328   CheckpointReleaseOperation cro(mspace, thread, false);
   310   CheckpointReleaseOperation cro(mspace, Thread::current(), false);
   329   CheckpointWriteOperation cpwo(&mwo, &cro);
   311   CompositeOperation<WriterHost<WriteOperation>, CheckpointReleaseOperation> co(&wh, &cro);
   330   assert(mspace->is_full_empty(), "invariant");
   312   assert(mspace->is_full_empty(), "invariant");
   331   process_free_list(cpwo, mspace);
   313   process_free_list(co, mspace);
   332   return wo.processed();
   314   return wo.processed();
   333 }
   315 }
   334 
   316 
       
   317 void JfrCheckpointManager::synchronize_epoch() {
       
   318   assert(_checkpoint_epoch_state != JfrTraceIdEpoch::epoch(), "invariant");
       
   319   OrderAccess::storestore();
       
   320   _checkpoint_epoch_state = JfrTraceIdEpoch::epoch();
       
   321 }
       
   322 
   335 size_t JfrCheckpointManager::write() {
   323 size_t JfrCheckpointManager::write() {
   336   const size_t processed = write_mspace_exclusive(_free_list_mspace, _chunkwriter);
   324   const size_t processed = write_mspace<MutexedWriteOp, CompositeOperation>(_free_list_mspace, _chunkwriter);
   337   synchronize_epoch();
   325   synchronize_epoch();
   338   return processed;
   326   return processed;
   339 }
   327 }
   340 
   328 
   341 size_t JfrCheckpointManager::write_epoch_transition_mspace() {
   329 size_t JfrCheckpointManager::write_epoch_transition_mspace() {
   342   return write_mspace_exclusive(_epoch_transition_mspace, _chunkwriter);
   330   return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
   343 }
   331 }
   344 
   332 
   345 typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
   333 typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
   346 size_t JfrCheckpointManager::clear() {
   334 size_t JfrCheckpointManager::clear() {
   347   DiscardOperation discarder(mutexed); // mutexed discard mode
   335   DiscardOperation discarder(mutexed); // mutexed discard mode
   371 void JfrCheckpointManager::write_type_set_for_unloaded_classes() {
   359 void JfrCheckpointManager::write_type_set_for_unloaded_classes() {
   372   assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   360   assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   373   JfrTypeManager::write_type_set_for_unloaded_classes();
   361   JfrTypeManager::write_type_set_for_unloaded_classes();
   374 }
   362 }
   375 
   363 
   376 void JfrCheckpointManager::create_thread_checkpoint(JavaThread* jt) {
   364 void JfrCheckpointManager::create_thread_blob(JavaThread* jt) {
   377   JfrTypeManager::create_thread_checkpoint(jt);
   365   JfrTypeManager::create_thread_blob(jt);
   378 }
   366 }
   379 
   367 
   380 void JfrCheckpointManager::write_thread_checkpoint(JavaThread* jt) {
   368 void JfrCheckpointManager::write_thread_checkpoint(JavaThread* jt) {
   381   JfrTypeManager::write_thread_checkpoint(jt);
   369   JfrTypeManager::write_thread_checkpoint(jt);
   382 }
   370 }
       
   371 
       
   372 void JfrCheckpointManager::shift_epoch() {
       
   373   debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
       
   374   JfrTraceIdEpoch::shift_epoch();
       
   375   assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
       
   376 }