diff -r 2c3cc4b01880 -r c16ac7a2eba4 src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp --- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp Wed Oct 30 16:14:56 2019 +0100 +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp Wed Oct 30 19:43:52 2019 +0100 @@ -26,6 +26,7 @@ #include "jfr/jfrEvents.hpp" #include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/recorder/jfrRecorder.hpp" +#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/service/jfrPostBox.hpp" @@ -253,6 +254,18 @@ assert(buffer->empty(), "invariant"); return true; } + + if (buffer->excluded()) { + const bool thread_is_excluded = thread->jfr_thread_local()->is_excluded(); + buffer->reinitialize(thread_is_excluded); + assert(buffer->empty(), "invariant"); + if (!thread_is_excluded) { + // state change from exclusion to inclusion requires a thread checkpoint + JfrCheckpointManager::write_thread_checkpoint(thread); + } + return true; + } + BufferPtr const promotion_buffer = get_promotion_buffer(unflushed_size, _global_mspace, *this, promotion_retry, thread); if (promotion_buffer == NULL) { write_data_loss(buffer, thread); @@ -301,7 +314,7 @@ assert(buffer != NULL, "invariant"); assert(buffer->retired(), "invariant"); const size_t unflushed_size = buffer->unflushed_size(); - buffer->reinitialize(); + buffer->concurrent_reinitialization(); log_registration_failure(unflushed_size); } @@ -470,6 +483,7 @@ assert(t != NULL, "invariant"); assert(cur != NULL, "invariant"); assert(cur->lease(), "invariant"); + assert(!cur->excluded(), "invariant"); assert(cur_pos != NULL, "invariant"); assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant"); assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant"); @@ -496,6 +510,9 @@ // the case for stable thread local buffers; it is not the case for large buffers. if (!cur->empty()) { flush_regular_buffer(cur, t); + if (cur->excluded()) { + return cur; + } } assert(t->jfr_thread_local()->shelved_buffer() == NULL, "invariant"); if (cur->free_size() >= req) { @@ -584,28 +601,40 @@ typedef UnBufferedWriteToChunk WriteOperation; typedef MutexedWriteOp MutexedWriteOperation; typedef ConcurrentWriteOp ConcurrentWriteOperation; -typedef ConcurrentWriteOpExcludeRetired ThreadLocalConcurrentWriteOperation; + +typedef Retired NonRetired; +typedef Excluded NonExcluded; +typedef CompositeOperation BufferPredicate; +typedef PredicatedMutexedWriteOp ThreadLocalMutexedWriteOperation; +typedef PredicatedConcurrentWriteOp ThreadLocalConcurrentWriteOperation; size_t JfrStorage::write() { - const size_t full_size_processed = write_full(); + const size_t full_elements = write_full(); WriteOperation wo(_chunkwriter); - ThreadLocalConcurrentWriteOperation tlwo(wo); + NonRetired nr; + NonExcluded ne; + BufferPredicate bp(&nr, &ne); + ThreadLocalConcurrentWriteOperation tlwo(wo, bp); process_full_list(tlwo, _thread_local_mspace); ConcurrentWriteOperation cwo(wo); process_free_list(cwo, _global_mspace); - return full_size_processed + wo.processed(); + return full_elements + wo.elements(); } size_t JfrStorage::write_at_safepoint() { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); WriteOperation wo(_chunkwriter); MutexedWriteOperation writer(wo); // mutexed write mode - process_full_list(writer, _thread_local_mspace); + NonRetired nr; + NonExcluded ne; + BufferPredicate bp(&nr, &ne); + ThreadLocalMutexedWriteOperation tlmwo(wo, bp); + process_full_list(tlmwo, _thread_local_mspace); assert(_transient_mspace->is_free_empty(), "invariant"); process_full_list(writer, _transient_mspace); assert(_global_mspace->is_full_empty(), "invariant"); process_free_list(writer, _global_mspace); - return wo.processed(); + return wo.elements(); } typedef DiscardOp > DiscardOperation; @@ -613,14 +642,14 @@ typedef CompositeOperation FullOperation; size_t JfrStorage::clear() { - const size_t full_size_processed = clear_full(); + const size_t full_elements = clear_full(); DiscardOperation discarder(concurrent); // concurrent discard mode process_full_list(discarder, _thread_local_mspace); assert(_transient_mspace->is_free_empty(), "invariant"); process_full_list(discarder, _transient_mspace); assert(_global_mspace->is_full_empty(), "invariant"); process_free_list(discarder, _global_mspace); - return full_size_processed + discarder.processed(); + return full_elements + discarder.elements(); } static void insert_free_age_nodes(JfrStorageAgeMspace* age_mspace, JfrAgeNode* head, JfrAgeNode* tail, size_t count) { @@ -711,15 +740,25 @@ ReleaseOperation ro(_transient_mspace, thread); FullOperation cmd(&writer, &ro); const size_t count = process_full(cmd, control(), _age_mspace); - log(count, writer.processed()); - return writer.processed(); + if (0 == count) { + assert(0 == writer.elements(), "invariant"); + return 0; + } + const size_t size = writer.size(); + log(count, size); + return count; } size_t JfrStorage::clear_full() { DiscardOperation discarder(mutexed); // a retired buffer implies mutexed access const size_t count = process_full(discarder, control(), _age_mspace); - log(count, discarder.processed(), true); - return discarder.processed(); + if (0 == count) { + assert(0 == discarder.elements(), "invariant"); + return 0; + } + const size_t size = discarder.size(); + log(count, size, true); + return count; } static void scavenge_log(size_t count, size_t amount, size_t current) { @@ -749,6 +788,10 @@ assert(!t->lease(), "invariant"); ++_count; _amount += t->total_size(); + if (t->excluded()) { + t->clear_excluded(); + } + assert(!t->excluded(), "invariant"); t->clear_retired(); t->release(); _control.decrement_dead(); @@ -767,6 +810,11 @@ } Scavenger scavenger(ctrl, _thread_local_mspace); process_full_list(scavenger, _thread_local_mspace); - scavenge_log(scavenger.processed(), scavenger.amount(), ctrl.dead_count()); - return scavenger.processed(); + const size_t count = scavenger.processed(); + if (0 == count) { + assert(0 == scavenger.amount(), "invariant"); + return 0; + } + scavenge_log(count, scavenger.amount(), ctrl.dead_count()); + return count; }