src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp
changeset 58863 c16ac7a2eba4
parent 55053 d58e1a447d2b
child 58967 3c2e49d43ba3
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "jfr/jfrEvents.hpp"
    26 #include "jfr/jfrEvents.hpp"
    27 #include "jfr/jni/jfrJavaSupport.hpp"
    27 #include "jfr/jni/jfrJavaSupport.hpp"
    28 #include "jfr/recorder/jfrRecorder.hpp"
    28 #include "jfr/recorder/jfrRecorder.hpp"
       
    29 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
    29 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
    30 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
    30 #include "jfr/recorder/service/jfrOptionSet.hpp"
    31 #include "jfr/recorder/service/jfrOptionSet.hpp"
    31 #include "jfr/recorder/service/jfrPostBox.hpp"
    32 #include "jfr/recorder/service/jfrPostBox.hpp"
    32 #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
    33 #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
    33 #include "jfr/recorder/storage/jfrStorage.hpp"
    34 #include "jfr/recorder/storage/jfrStorage.hpp"
   251   if (unflushed_size == 0) {
   252   if (unflushed_size == 0) {
   252     buffer->concurrent_reinitialization();
   253     buffer->concurrent_reinitialization();
   253     assert(buffer->empty(), "invariant");
   254     assert(buffer->empty(), "invariant");
   254     return true;
   255     return true;
   255   }
   256   }
       
   257 
       
   258   if (buffer->excluded()) {
       
   259     const bool thread_is_excluded = thread->jfr_thread_local()->is_excluded();
       
   260     buffer->reinitialize(thread_is_excluded);
       
   261     assert(buffer->empty(), "invariant");
       
   262     if (!thread_is_excluded) {
       
   263       // state change from exclusion to inclusion requires a thread checkpoint
       
   264       JfrCheckpointManager::write_thread_checkpoint(thread);
       
   265     }
       
   266     return true;
       
   267   }
       
   268 
   256   BufferPtr const promotion_buffer = get_promotion_buffer(unflushed_size, _global_mspace, *this, promotion_retry, thread);
   269   BufferPtr const promotion_buffer = get_promotion_buffer(unflushed_size, _global_mspace, *this, promotion_retry, thread);
   257   if (promotion_buffer == NULL) {
   270   if (promotion_buffer == NULL) {
   258     write_data_loss(buffer, thread);
   271     write_data_loss(buffer, thread);
   259     return false;
   272     return false;
   260   }
   273   }
   299 
   312 
   300 static void handle_registration_failure(BufferPtr buffer) {
   313 static void handle_registration_failure(BufferPtr buffer) {
   301   assert(buffer != NULL, "invariant");
   314   assert(buffer != NULL, "invariant");
   302   assert(buffer->retired(), "invariant");
   315   assert(buffer->retired(), "invariant");
   303   const size_t unflushed_size = buffer->unflushed_size();
   316   const size_t unflushed_size = buffer->unflushed_size();
   304   buffer->reinitialize();
   317   buffer->concurrent_reinitialization();
   305   log_registration_failure(unflushed_size);
   318   log_registration_failure(unflushed_size);
   306 }
   319 }
   307 
   320 
   308 static JfrAgeNode* get_free_age_node(JfrStorageAgeMspace* age_mspace, Thread* thread) {
   321 static JfrAgeNode* get_free_age_node(JfrStorageAgeMspace* age_mspace, Thread* thread) {
   309   assert(JfrBuffer_lock->owned_by_self(), "invariant");
   322   assert(JfrBuffer_lock->owned_by_self(), "invariant");
   468 
   481 
   469 static void assert_flush_large_precondition(ConstBufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
   482 static void assert_flush_large_precondition(ConstBufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
   470   assert(t != NULL, "invariant");
   483   assert(t != NULL, "invariant");
   471   assert(cur != NULL, "invariant");
   484   assert(cur != NULL, "invariant");
   472   assert(cur->lease(), "invariant");
   485   assert(cur->lease(), "invariant");
       
   486   assert(!cur->excluded(), "invariant");
   473   assert(cur_pos != NULL, "invariant");
   487   assert(cur_pos != NULL, "invariant");
   474   assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant");
   488   assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant");
   475   assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant");
   489   assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant");
   476   assert(req >= used, "invariant");
   490   assert(req >= used, "invariant");
   477   assert(cur != t->jfr_thread_local()->shelved_buffer(), "invariant");
   491   assert(cur != t->jfr_thread_local()->shelved_buffer(), "invariant");
   494   // which is where the "used / uncommitted" data resides. It is therefore both
   508   // which is where the "used / uncommitted" data resides. It is therefore both
   495   // possible and valid to migrate data after the flush. This is however only
   509   // possible and valid to migrate data after the flush. This is however only
   496   // the case for stable thread local buffers; it is not the case for large buffers.
   510   // the case for stable thread local buffers; it is not the case for large buffers.
   497   if (!cur->empty()) {
   511   if (!cur->empty()) {
   498     flush_regular_buffer(cur, t);
   512     flush_regular_buffer(cur, t);
       
   513     if (cur->excluded()) {
       
   514       return cur;
       
   515     }
   499   }
   516   }
   500   assert(t->jfr_thread_local()->shelved_buffer() == NULL, "invariant");
   517   assert(t->jfr_thread_local()->shelved_buffer() == NULL, "invariant");
   501   if (cur->free_size() >= req) {
   518   if (cur->free_size() >= req) {
   502     // simplest case, no switching of buffers
   519     // simplest case, no switching of buffers
   503     if (used > 0) {
   520     if (used > 0) {
   582 }
   599 }
   583 
   600 
   584 typedef UnBufferedWriteToChunk<JfrBuffer> WriteOperation;
   601 typedef UnBufferedWriteToChunk<JfrBuffer> WriteOperation;
   585 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
   602 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
   586 typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation;
   603 typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation;
   587 typedef ConcurrentWriteOpExcludeRetired<WriteOperation> ThreadLocalConcurrentWriteOperation;
   604 
       
   605 typedef Retired<JfrBuffer, true> NonRetired;
       
   606 typedef Excluded<JfrBuffer, true> NonExcluded;
       
   607 typedef CompositeOperation<NonRetired, NonExcluded> BufferPredicate;
       
   608 typedef PredicatedMutexedWriteOp<WriteOperation, BufferPredicate> ThreadLocalMutexedWriteOperation;
       
   609 typedef PredicatedConcurrentWriteOp<WriteOperation, BufferPredicate> ThreadLocalConcurrentWriteOperation;
   588 
   610 
   589 size_t JfrStorage::write() {
   611 size_t JfrStorage::write() {
   590   const size_t full_size_processed = write_full();
   612   const size_t full_elements = write_full();
   591   WriteOperation wo(_chunkwriter);
   613   WriteOperation wo(_chunkwriter);
   592   ThreadLocalConcurrentWriteOperation tlwo(wo);
   614   NonRetired nr;
       
   615   NonExcluded ne;
       
   616   BufferPredicate bp(&nr, &ne);
       
   617   ThreadLocalConcurrentWriteOperation tlwo(wo, bp);
   593   process_full_list(tlwo, _thread_local_mspace);
   618   process_full_list(tlwo, _thread_local_mspace);
   594   ConcurrentWriteOperation cwo(wo);
   619   ConcurrentWriteOperation cwo(wo);
   595   process_free_list(cwo, _global_mspace);
   620   process_free_list(cwo, _global_mspace);
   596   return full_size_processed + wo.processed();
   621   return full_elements + wo.elements();
   597 }
   622 }
   598 
   623 
   599 size_t JfrStorage::write_at_safepoint() {
   624 size_t JfrStorage::write_at_safepoint() {
   600   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   625   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   601   WriteOperation wo(_chunkwriter);
   626   WriteOperation wo(_chunkwriter);
   602   MutexedWriteOperation writer(wo); // mutexed write mode
   627   MutexedWriteOperation writer(wo); // mutexed write mode
   603   process_full_list(writer, _thread_local_mspace);
   628   NonRetired nr;
       
   629   NonExcluded ne;
       
   630   BufferPredicate bp(&nr, &ne);
       
   631   ThreadLocalMutexedWriteOperation tlmwo(wo, bp);
       
   632   process_full_list(tlmwo, _thread_local_mspace);
   604   assert(_transient_mspace->is_free_empty(), "invariant");
   633   assert(_transient_mspace->is_free_empty(), "invariant");
   605   process_full_list(writer, _transient_mspace);
   634   process_full_list(writer, _transient_mspace);
   606   assert(_global_mspace->is_full_empty(), "invariant");
   635   assert(_global_mspace->is_full_empty(), "invariant");
   607   process_free_list(writer, _global_mspace);
   636   process_free_list(writer, _global_mspace);
   608   return wo.processed();
   637   return wo.elements();
   609 }
   638 }
   610 
   639 
   611 typedef DiscardOp<DefaultDiscarder<JfrStorage::Buffer> > DiscardOperation;
   640 typedef DiscardOp<DefaultDiscarder<JfrStorage::Buffer> > DiscardOperation;
   612 typedef ReleaseOp<JfrStorageMspace> ReleaseOperation;
   641 typedef ReleaseOp<JfrStorageMspace> ReleaseOperation;
   613 typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> FullOperation;
   642 typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> FullOperation;
   614 
   643 
   615 size_t JfrStorage::clear() {
   644 size_t JfrStorage::clear() {
   616   const size_t full_size_processed = clear_full();
   645   const size_t full_elements = clear_full();
   617   DiscardOperation discarder(concurrent); // concurrent discard mode
   646   DiscardOperation discarder(concurrent); // concurrent discard mode
   618   process_full_list(discarder, _thread_local_mspace);
   647   process_full_list(discarder, _thread_local_mspace);
   619   assert(_transient_mspace->is_free_empty(), "invariant");
   648   assert(_transient_mspace->is_free_empty(), "invariant");
   620   process_full_list(discarder, _transient_mspace);
   649   process_full_list(discarder, _transient_mspace);
   621   assert(_global_mspace->is_full_empty(), "invariant");
   650   assert(_global_mspace->is_full_empty(), "invariant");
   622   process_free_list(discarder, _global_mspace);
   651   process_free_list(discarder, _global_mspace);
   623   return full_size_processed + discarder.processed();
   652   return full_elements + discarder.elements();
   624 }
   653 }
   625 
   654 
   626 static void insert_free_age_nodes(JfrStorageAgeMspace* age_mspace, JfrAgeNode* head, JfrAgeNode* tail, size_t count) {
   655 static void insert_free_age_nodes(JfrStorageAgeMspace* age_mspace, JfrAgeNode* head, JfrAgeNode* tail, size_t count) {
   627   if (tail != NULL) {
   656   if (tail != NULL) {
   628     assert(tail->next() == NULL, "invariant");
   657     assert(tail->next() == NULL, "invariant");
   709   WriteOperation wo(_chunkwriter);
   738   WriteOperation wo(_chunkwriter);
   710   MutexedWriteOperation writer(wo); // a retired buffer implies mutexed access
   739   MutexedWriteOperation writer(wo); // a retired buffer implies mutexed access
   711   ReleaseOperation ro(_transient_mspace, thread);
   740   ReleaseOperation ro(_transient_mspace, thread);
   712   FullOperation cmd(&writer, &ro);
   741   FullOperation cmd(&writer, &ro);
   713   const size_t count = process_full(cmd, control(), _age_mspace);
   742   const size_t count = process_full(cmd, control(), _age_mspace);
   714   log(count, writer.processed());
   743   if (0 == count) {
   715   return writer.processed();
   744     assert(0 == writer.elements(), "invariant");
       
   745     return 0;
       
   746   }
       
   747   const size_t size = writer.size();
       
   748   log(count, size);
       
   749   return count;
   716 }
   750 }
   717 
   751 
   718 size_t JfrStorage::clear_full() {
   752 size_t JfrStorage::clear_full() {
   719   DiscardOperation discarder(mutexed); // a retired buffer implies mutexed access
   753   DiscardOperation discarder(mutexed); // a retired buffer implies mutexed access
   720   const size_t count = process_full(discarder, control(), _age_mspace);
   754   const size_t count = process_full(discarder, control(), _age_mspace);
   721   log(count, discarder.processed(), true);
   755   if (0 == count) {
   722   return discarder.processed();
   756     assert(0 == discarder.elements(), "invariant");
       
   757     return 0;
       
   758   }
       
   759   const size_t size = discarder.size();
       
   760   log(count, size, true);
       
   761   return count;
   723 }
   762 }
   724 
   763 
   725 static void scavenge_log(size_t count, size_t amount, size_t current) {
   764 static void scavenge_log(size_t count, size_t amount, size_t current) {
   726   if (count > 0) {
   765   if (count > 0) {
   727     if (log_is_enabled(Debug, jfr, system)) {
   766     if (log_is_enabled(Debug, jfr, system)) {
   747       assert(t->empty(), "invariant");
   786       assert(t->empty(), "invariant");
   748       assert(!t->transient(), "invariant");
   787       assert(!t->transient(), "invariant");
   749       assert(!t->lease(), "invariant");
   788       assert(!t->lease(), "invariant");
   750       ++_count;
   789       ++_count;
   751       _amount += t->total_size();
   790       _amount += t->total_size();
       
   791       if (t->excluded()) {
       
   792         t->clear_excluded();
       
   793       }
       
   794       assert(!t->excluded(), "invariant");
   752       t->clear_retired();
   795       t->clear_retired();
   753       t->release();
   796       t->release();
   754       _control.decrement_dead();
   797       _control.decrement_dead();
   755       mspace_release_full_critical(t, _mspace);
   798       mspace_release_full_critical(t, _mspace);
   756     }
   799     }
   765   if (ctrl.dead_count() == 0) {
   808   if (ctrl.dead_count() == 0) {
   766     return 0;
   809     return 0;
   767   }
   810   }
   768   Scavenger<JfrThreadLocalMspace> scavenger(ctrl, _thread_local_mspace);
   811   Scavenger<JfrThreadLocalMspace> scavenger(ctrl, _thread_local_mspace);
   769   process_full_list(scavenger, _thread_local_mspace);
   812   process_full_list(scavenger, _thread_local_mspace);
   770   scavenge_log(scavenger.processed(), scavenger.amount(), ctrl.dead_count());
   813   const size_t count = scavenger.processed();
   771   return scavenger.processed();
   814   if (0 == count) {
   772 }
   815     assert(0 == scavenger.amount(), "invariant");
       
   816     return 0;
       
   817   }
       
   818   scavenge_log(count, scavenger.amount(), ctrl.dead_count());
       
   819   return count;
       
   820 }