From 35d17a00ab4028071a8fc7cd781b3306e6811970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Mon, 10 Oct 2022 12:39:10 +0000 Subject: [PATCH] 8293864: Kitchensink24HStress.java fails with SIGSEGV in JfrCheckpointManager::lease Reviewed-by: egahlin --- .../checkpoint/jfrCheckpointManager.cpp | 227 +++++++++++------- .../checkpoint/jfrCheckpointManager.hpp | 14 +- .../checkpoint/jfrCheckpointWriter.cpp | 13 +- .../checkpoint/jfrCheckpointWriter.hpp | 6 +- .../checkpoint/types/jfrTypeManager.cpp | 7 +- .../share/jfr/recorder/storage/jfrBuffer.cpp | 8 +- .../share/jfr/recorder/storage/jfrBuffer.hpp | 4 +- .../storage/jfrMemorySpace.inline.hpp | 5 +- src/hotspot/share/jfr/utilities/jfrTypes.hpp | 6 + 9 files changed, 173 insertions(+), 117 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index 0fbe3029586..edbbb5c76cf 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -56,6 +56,7 @@ #include "runtime/safepoint.hpp" typedef JfrCheckpointManager::BufferPtr BufferPtr; +typedef JfrCheckpointManager::ConstBufferPtr ConstBufferPtr; static JfrSignal _new_checkpoint; static JfrCheckpointManager* _instance = NULL; @@ -77,8 +78,9 @@ void JfrCheckpointManager::destroy() { } JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) : - _global_mspace(NULL), - _thread_local_mspace(NULL), + _global_mspace(nullptr), + _thread_local_mspace(nullptr), + _virtual_thread_local_mspace(nullptr), _chunkwriter(cw) {} JfrCheckpointManager::~JfrCheckpointManager() { @@ -91,8 +93,11 @@ JfrCheckpointManager::~JfrCheckpointManager() { static const size_t global_buffer_prealloc_count = 2; static const size_t global_buffer_size = 512 * K; -static const size_t thread_local_buffer_prealloc_count = 32; -static const size_t thread_local_buffer_size = 4 * K; +static const size_t thread_local_buffer_prealloc_count = 16; +static const size_t thread_local_buffer_size = 256; + +static const size_t virtual_thread_local_buffer_prealloc_count = 0; +static const size_t virtual_thread_local_buffer_size = 4 * K; bool JfrCheckpointManager::initialize() { assert(_global_mspace == NULL, "invariant"); @@ -110,27 +115,35 @@ bool JfrCheckpointManager::initialize() { assert(_thread_local_mspace == NULL, "invariant"); _thread_local_mspace = new JfrThreadLocalCheckpointMspace(); if (_thread_local_mspace == NULL || !_thread_local_mspace->initialize(thread_local_buffer_size, - JFR_MSPACE_UNLIMITED_CACHE_SIZE, + thread_local_buffer_prealloc_count, thread_local_buffer_prealloc_count)) { return false; } + + assert(_virtual_thread_local_mspace == NULL, "invariant"); + _virtual_thread_local_mspace = new JfrThreadLocalCheckpointMspace(); + if (_virtual_thread_local_mspace == NULL || !_virtual_thread_local_mspace->initialize(virtual_thread_local_buffer_size, + JFR_MSPACE_UNLIMITED_CACHE_SIZE, + virtual_thread_local_buffer_prealloc_count)) { + return false; + } return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize(); } #ifdef ASSERT -static void assert_lease(const BufferPtr buffer) { +static void assert_lease(ConstBufferPtr buffer) { assert(buffer != NULL, "invariant"); assert(buffer->acquired_by_self(), "invariant"); assert(buffer->lease(), "invariant"); } -static void assert_release(const BufferPtr buffer) { +static void assert_release(ConstBufferPtr buffer) { assert(buffer != NULL, "invariant"); assert(buffer->lease(), "invariant"); assert(buffer->acquired_by_self(), "invariant"); } -static void assert_retired(const BufferPtr buffer, Thread* thread) { +static void assert_retired(ConstBufferPtr buffer, Thread* thread) { assert(buffer != NULL, "invariant"); assert(buffer->acquired_by(thread), "invariant"); assert(buffer->retired(), "invariant"); @@ -142,7 +155,22 @@ void JfrCheckpointManager::register_full(BufferPtr buffer, Thread* thread) { // nothing here at the moment } -BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) { +static inline bool is_global(ConstBufferPtr buffer) { + assert(buffer != NULL, "invariant"); + return buffer->context() == JFR_GLOBAL; +} + +static inline bool is_thread_local(ConstBufferPtr buffer) { + assert(buffer != NULL, "invariant"); + return buffer->context() == JFR_THREADLOCAL; +} + +static inline bool is_virtual_thread_local(ConstBufferPtr buffer) { + assert(buffer != NULL, "invariant"); + return buffer->context() == JFR_VIRTUAL_THREADLOCAL; +} + +BufferPtr JfrCheckpointManager::lease_global(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) { JfrCheckpointMspace* const mspace = instance()._global_mspace; assert(mspace != NULL, "invariant"); static const size_t max_elem_size = mspace->min_element_size(); // min is max @@ -160,38 +188,24 @@ BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* fal return buffer; } -const u1 thread_local_context = 1; - -static bool is_thread_local(const JfrBuffer* buffer) { - assert(buffer != NULL, "invariant"); - return buffer->context() == thread_local_context; +BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size) { + BufferPtr buffer = instance()._thread_local_mspace->acquire(size, thread); + assert(buffer != nullptr, "invariant"); + assert(buffer->free_size() >= size, "invariant"); + buffer->set_lease(); + DEBUG_ONLY(assert_lease(buffer);) + buffer->set_context(JFR_THREADLOCAL); + assert(is_thread_local(buffer), "invariant"); + return buffer; } -static void retire(JfrBuffer* buffer) { - DEBUG_ONLY(assert_release(buffer);) - buffer->clear_lease(); - buffer->set_retired(); -} - -/* - * The buffer is effectively invalidated for the thread post-return, - * and the caller should take means to ensure that it is not referenced. - */ -static void release(JfrBuffer* buffer) { - DEBUG_ONLY(assert_release(buffer);) - if (!is_thread_local(buffer)) { - buffer->clear_lease(); - buffer->release(); - } -} - -BufferPtr JfrCheckpointManager::get_thread_local(Thread* thread) { +BufferPtr JfrCheckpointManager::get_virtual_thread_local(Thread* thread) { assert(thread != NULL, "invariant"); return JfrTraceIdEpoch::epoch() ? thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 : thread->jfr_thread_local()->_checkpoint_buffer_epoch_0; } -void JfrCheckpointManager::set_thread_local(Thread* thread, BufferPtr buffer) { +void JfrCheckpointManager::set_virtual_thread_local(Thread* thread, BufferPtr buffer) { assert(thread != NULL, "invariant"); if (JfrTraceIdEpoch::epoch()) { thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 = buffer; @@ -200,49 +214,85 @@ void JfrCheckpointManager::set_thread_local(Thread* thread, BufferPtr buffer) { } } -BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) { - assert(thread != NULL, "invariant"); - JfrBuffer* const buffer = instance()._thread_local_mspace->acquire(size, thread); - assert(buffer != NULL, "invariant"); +BufferPtr JfrCheckpointManager::new_virtual_thread_local(Thread* thread, size_t size) { + BufferPtr buffer = instance()._virtual_thread_local_mspace->acquire(size, thread); + assert(buffer != nullptr, "invariant"); assert(buffer->free_size() >= size, "invariant"); - buffer->set_context(thread_local_context); - assert(is_thread_local(buffer), "invariant"); - buffer->set_lease(); - set_thread_local(thread, buffer); + buffer->set_context(JFR_VIRTUAL_THREADLOCAL); + assert(is_virtual_thread_local(buffer), "invariant"); + set_virtual_thread_local(thread, buffer); return buffer; } -BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) { - JfrBuffer* buffer = get_thread_local(thread); - if (buffer == NULL) { - buffer = acquire_thread_local(size, thread); - } else if (buffer->free_size() < size) { - retire(buffer); - buffer = acquire_thread_local(size, thread); +BufferPtr JfrCheckpointManager::acquire_virtual_thread_local(Thread* thread, size_t size /* 0 */) { + BufferPtr buffer = get_virtual_thread_local(thread); + if (buffer == nullptr || buffer->free_size() < size) { + buffer = new_virtual_thread_local(thread, size); } - DEBUG_ONLY(assert_lease(buffer);) + assert(buffer->acquired_by_self(), "invariant"); assert(buffer->free_size() >= size, "invariant"); - assert(get_thread_local(thread) == buffer, "invariant"); + assert(get_virtual_thread_local(thread) == buffer, "invariant"); + assert(is_virtual_thread_local(buffer), "invariant"); return buffer; } -BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) { +BufferPtr JfrCheckpointManager::renew(ConstBufferPtr old, Thread* thread, size_t size, JfrCheckpointBufferKind kind /* JFR_THREADLOCAL */) { assert(old != NULL, "invariant"); - return is_thread_local(old) ? acquire_thread_local(size, thread) : - lease(thread, instance()._global_mspace->in_previous_epoch_list(old), size); + assert(old->acquired_by_self(), "invariant"); + if (kind == JFR_GLOBAL) { + return lease_global(thread, instance()._global_mspace->in_previous_epoch_list(old), size); + } + return kind == JFR_THREADLOCAL ? lease_thread_local(thread, size) : acquire_virtual_thread_local(thread, size); +} + +BufferPtr JfrCheckpointManager::acquire(Thread* thread, JfrCheckpointBufferKind kind /* JFR_THREADLOCAL */, bool previous_epoch /* false */, size_t size /* 0 */) { + if (kind == JFR_GLOBAL) { + return lease_global(thread, previous_epoch, size); + } + if (kind == JFR_THREADLOCAL) { + return lease_thread_local(thread, size); + } + assert(kind == JFR_VIRTUAL_THREADLOCAL, "invariant"); + return acquire_virtual_thread_local(thread, size); +} + +static inline void retire(BufferPtr buffer) { + assert(buffer != nullptr, "invariant"); + assert(buffer->acquired_by_self(), "invariant"); + buffer->set_retired(); +} + +/* + * The buffer is effectively invalidated for the thread post-return, + * and the caller should take means to ensure that it is not referenced. + */ +static inline void release(BufferPtr buffer) { + DEBUG_ONLY(assert_release(buffer);) + assert(!is_virtual_thread_local(buffer), "invariant"); + if (is_global(buffer)) { + buffer->release(); + return; + } + assert(is_thread_local(buffer), "invariant"); + retire(buffer); +} + +static inline JfrCheckpointBufferKind kind(ConstBufferPtr buffer) { + assert(buffer != nullptr, "invariant"); + return static_cast(buffer->context()); } BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) { assert(old != NULL, "invariant"); - assert(old->lease(), "invariant"); if (0 == requested) { // indicates a lease is being returned + assert(old->lease(), "invariant"); release(old); // signal completion of a new checkpoint _new_checkpoint.signal(); return NULL; } - BufferPtr new_buffer = lease(old, thread, used + requested); + BufferPtr new_buffer = renew(old, thread, used + requested, kind(old)); assert(new_buffer != NULL, "invariant"); migrate_outstanding_writes(old, new_buffer, used, requested); retire(old); @@ -372,7 +422,7 @@ class CheckpointWriteOp { // This op will collapse all individual vthread checkpoints into a single checkpoint. template -class ThreadLocalCheckpointWriteOp { +class VirtualThreadLocalCheckpointWriteOp { private: JfrChunkWriter& _cw; int64_t _begin_offset; @@ -381,7 +431,7 @@ class ThreadLocalCheckpointWriteOp { u4 _elements; public: typedef T Type; - ThreadLocalCheckpointWriteOp(JfrChunkWriter& cw) : _cw(cw), _begin_offset(cw.current_offset()), _elements_offset(0), _processed(0), _elements(0) { + VirtualThreadLocalCheckpointWriteOp(JfrChunkWriter& cw) : _cw(cw), _begin_offset(cw.current_offset()), _elements_offset(0), _processed(0), _elements(0) { const int64_t last_checkpoint = cw.last_checkpoint_offset(); const int64_t delta = last_checkpoint == 0 ? 0 : last_checkpoint - _begin_offset; cw.reserve(sizeof(u4)); @@ -396,7 +446,7 @@ class ThreadLocalCheckpointWriteOp { cw.reserve(sizeof(u4)); } - ~ThreadLocalCheckpointWriteOp() { + ~VirtualThreadLocalCheckpointWriteOp() { if (_elements == 0) { // Rewind. _cw.seek(_begin_offset); @@ -417,11 +467,11 @@ class ThreadLocalCheckpointWriteOp { }; typedef CheckpointWriteOp WriteOperation; -typedef ThreadLocalCheckpointWriteOp ThreadLocalCheckpointOperation; -typedef MutexedWriteOp ThreadLocalWriteOperation; +typedef MutexedWriteOp MutexedWriteOperation; typedef ReleaseWithExcisionOp ReleaseOperation; -typedef ExclusiveOp GlobalWriteOperation; -typedef CompositeOperation GlobalWriteReleaseOperation; +typedef CompositeOperation WriteReleaseOperation; +typedef VirtualThreadLocalCheckpointWriteOp VirtualThreadLocalCheckpointOperation; +typedef MutexedWriteOp VirtualThreadLocalWriteOperation; void JfrCheckpointManager::begin_epoch_shift() { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); @@ -438,33 +488,33 @@ void JfrCheckpointManager::end_epoch_shift() { size_t JfrCheckpointManager::write() { DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current())); WriteOperation wo(_chunkwriter); - GlobalWriteOperation gwo(wo); + MutexedWriteOperation mwo(wo); + _thread_local_mspace->iterate(mwo, true); // previous epoch list assert(_global_mspace->free_list_is_empty(), "invariant"); - ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true)); - GlobalWriteReleaseOperation gwro(&gwo, &ro); - process_live_list(gwro, _global_mspace, true); // previous epoch list - // Do thread local list after global. Careful, the tlco destructor writes to chunk. - ThreadLocalCheckpointOperation tlco(_chunkwriter); - ThreadLocalWriteOperation tlwo(tlco); - _thread_local_mspace->iterate(tlwo, true); // previous epoch list - return wo.processed() + tlco.processed(); + ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true)); // previous epoch list + WriteReleaseOperation wro(&mwo, &ro); + process_live_list(wro, _global_mspace, true); // previous epoch list + // Do virtual thread local list last. Careful, the vtlco destructor writes to chunk. + VirtualThreadLocalCheckpointOperation vtlco(_chunkwriter); + VirtualThreadLocalWriteOperation vtlwo(vtlco); + _virtual_thread_local_mspace->iterate(vtlwo, true); // previous epoch list + return wo.processed() + vtlco.processed(); } -typedef DiscardOp > ThreadLocalDiscardOperation; -typedef ExclusiveDiscardOp > GlobalDiscardOperation; -typedef CompositeOperation DiscardReleaseOperation; +typedef DiscardOp > DiscardOperation; +typedef CompositeOperation DiscardReleaseOperation; size_t JfrCheckpointManager::clear() { JfrTraceIdLoadBarrier::clear(); clear_type_set(); - ThreadLocalDiscardOperation tldo(mutexed); // mutexed discard mode - _thread_local_mspace->iterate(tldo, true); // previous epoch list - GlobalDiscardOperation gdo(mutexed); // mutexed discard mode + DiscardOperation dop(mutexed); // mutexed discard mode + _thread_local_mspace->iterate(dop, true); // previous epoch list + _virtual_thread_local_mspace->iterate(dop, true); // previous epoch list ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true)); // previous epoch list - DiscardReleaseOperation dro(&gdo, &ro); + DiscardReleaseOperation dro(&dop, &ro); assert(_global_mspace->free_list_is_empty(), "invariant"); process_live_list(dro, _global_mspace, true); // previous epoch list - return tldo.elements() + gdo.elements(); + return dop.elements(); } size_t JfrCheckpointManager::write_static_type_set(Thread* thread) { @@ -561,17 +611,16 @@ size_t JfrCheckpointManager::flush_type_set() { } } if (_new_checkpoint.is_signaled_with_reset()) { + WriteOperation wo(_chunkwriter); + MutexedWriteOperation mwo(wo); + _thread_local_mspace->iterate(mwo); // current epoch list assert(_global_mspace->free_list_is_empty(), "invariant"); assert(_global_mspace->live_list_is_nonempty(), "invariant"); - WriteOperation wo(_chunkwriter); - GlobalWriteOperation gwo(wo); - ReleaseOperation ro(_global_mspace, _global_mspace->live_list()); // current epoch list - GlobalWriteReleaseOperation gwro(&gwo, &ro); - process_live_list(gwro, _global_mspace); // current epoch list - // Do thread local list after global. Careful, the tlco destructor writes to chunk. - ThreadLocalCheckpointOperation tlco(_chunkwriter); - ThreadLocalWriteOperation tlwo(tlco); - _thread_local_mspace->iterate(tlwo); // current epoch list + process_live_list(mwo, _global_mspace); // current epoch list + // Do virtual thread local list last. Careful, the vtlco destructor writes to chunk. + VirtualThreadLocalCheckpointOperation vtlco(_chunkwriter); + VirtualThreadLocalWriteOperation vtlwo(vtlco); + _virtual_thread_local_mspace->iterate(vtlwo); // current epoch list } return elements; } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp index 7c8dc7d617a..6b0bd081b90 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp @@ -57,9 +57,11 @@ class JfrCheckpointManager : public JfrCHeapObj { public: typedef JfrCheckpointMspace::Node Buffer; typedef JfrCheckpointMspace::NodePtr BufferPtr; + typedef const JfrCheckpointMspace::Node* ConstBufferPtr; private: JfrCheckpointMspace* _global_mspace; JfrThreadLocalCheckpointMspace* _thread_local_mspace; + JfrThreadLocalCheckpointMspace* _virtual_thread_local_mspace; JfrChunkWriter& _chunkwriter; JfrCheckpointManager(JfrChunkWriter& cw); @@ -69,14 +71,16 @@ class JfrCheckpointManager : public JfrCHeapObj { bool initialize(); static void destroy(); - static BufferPtr get_thread_local(Thread* thread); - static void set_thread_local(Thread* thread, BufferPtr buffer); - static BufferPtr acquire_thread_local(size_t size, Thread* thread); + static BufferPtr get_virtual_thread_local(Thread* thread); + static void set_virtual_thread_local(Thread* thread, BufferPtr buffer); + static BufferPtr acquire_virtual_thread_local(Thread* thread, size_t size); + static BufferPtr new_virtual_thread_local(Thread* thread, size_t size = 0); - static BufferPtr lease(Thread* thread, bool previous_epoch = false, size_t size = 0); - static BufferPtr lease(BufferPtr old, Thread* thread, size_t size); static BufferPtr lease_thread_local(Thread* thread, size_t size = 0); + static BufferPtr lease_global(Thread* thread, bool previous_epoch = false, size_t size = 0); + static BufferPtr acquire(Thread* thread, JfrCheckpointBufferKind kind = JFR_THREADLOCAL, bool previous_epoch = false, size_t size = 0); + static BufferPtr renew(ConstBufferPtr old, Thread* thread, size_t size, JfrCheckpointBufferKind kind = JFR_THREADLOCAL); static BufferPtr flush(BufferPtr old, size_t used, size_t requested, Thread* thread); size_t clear(); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp index 4085abbcd28..6fea14057f7 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp @@ -27,17 +27,18 @@ #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" #include "jfr/utilities/jfrBlob.hpp" #include "jfr/writers/jfrBigEndianWriter.hpp" +#include "runtime/thread.inline.hpp" JfrCheckpointFlush::JfrCheckpointFlush(Type* old, size_t used, size_t requested, Thread* t) : _result(JfrCheckpointManager::flush(old, used, requested, t)) {} -JfrCheckpointWriter::JfrCheckpointWriter(JfrCheckpointType type /* GENERIC */) : - JfrCheckpointWriterBase(JfrCheckpointManager::lease(Thread::current()), Thread::current()), +JfrCheckpointWriter::JfrCheckpointWriter(bool header /* true */, JfrCheckpointType type /* GENERIC */, JfrCheckpointBufferKind kind /* JFR_GLOBAL */) : + JfrCheckpointWriterBase(JfrCheckpointManager::acquire(Thread::current(), kind), Thread::current()), _time(JfrTicks::now()), _offset(0), _count(0), _type(type), - _header(true) { + _header(header) { assert(this->is_acquired(), "invariant"); assert(0 == this->current_offset(), "invariant"); if (_header) { @@ -45,8 +46,8 @@ JfrCheckpointWriter::JfrCheckpointWriter(JfrCheckpointType type /* GENERIC */) : } } -JfrCheckpointWriter::JfrCheckpointWriter(Thread* thread, bool header /* true */, JfrCheckpointType type /* GENERIC */, bool global_lease /* true */) : - JfrCheckpointWriterBase(global_lease ? JfrCheckpointManager::lease(thread) : JfrCheckpointManager::lease_thread_local(thread), thread), +JfrCheckpointWriter::JfrCheckpointWriter(Thread* thread, bool header /* true */, JfrCheckpointType type /* GENERIC */, JfrCheckpointBufferKind kind /* JFR_GLOBAL */) : + JfrCheckpointWriterBase(JfrCheckpointManager::acquire(thread, kind), thread), _time(JfrTicks::now()), _offset(0), _count(0), @@ -60,7 +61,7 @@ JfrCheckpointWriter::JfrCheckpointWriter(Thread* thread, bool header /* true */, } JfrCheckpointWriter::JfrCheckpointWriter(bool previous_epoch, Thread* thread, JfrCheckpointType type /* GENERIC */) : - JfrCheckpointWriterBase(JfrCheckpointManager::lease(thread, previous_epoch), thread), + JfrCheckpointWriterBase(JfrCheckpointManager::lease_global(thread, previous_epoch), thread), _time(JfrTicks::now()), _offset(0), _count(0), diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp index 3666d7f747b..bdbd4182204 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp @@ -70,9 +70,9 @@ class JfrCheckpointWriter : public JfrCheckpointWriterBase { const u1* session_data(size_t* size, bool move = false, const JfrCheckpointContext* ctx = NULL); void release(); JfrCheckpointWriter(bool previous_epoch, Thread* thread, JfrCheckpointType type = GENERIC); - public: - JfrCheckpointWriter(JfrCheckpointType type = GENERIC); - JfrCheckpointWriter(Thread* thread, bool header = true, JfrCheckpointType mode = GENERIC, bool global_lease = true); +public: + JfrCheckpointWriter(bool header = true, JfrCheckpointType mode = GENERIC, JfrCheckpointBufferKind kind = JFR_GLOBAL); + JfrCheckpointWriter(Thread* thread, bool header = true, JfrCheckpointType mode = GENERIC, JfrCheckpointBufferKind kind = JFR_GLOBAL); ~JfrCheckpointWriter(); void write_type(JfrTypeId type_id); void write_count(u4 nof_entries); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp index 913d13b78f4..5667c892aa8 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp @@ -36,6 +36,7 @@ #include "memory/resourceArea.hpp" #include "runtime/javaThread.hpp" #include "runtime/semaphore.hpp" +#include "runtime/thread.inline.hpp" #include "utilities/macros.hpp" class JfrSerializerRegistration : public JfrCHeapObj { @@ -104,7 +105,7 @@ void JfrTypeManager::write_threads(JfrCheckpointWriter& writer) { JfrBlobHandle JfrTypeManager::create_thread_blob(JavaThread* jt, traceid tid /* 0 */, oop vthread /* nullptr */) { assert(jt != NULL, "invariant"); ResourceMark rm(jt); - JfrCheckpointWriter writer(jt, true, THREADS, false); // Thread local lease for blob creation. + JfrCheckpointWriter writer(jt, true, THREADS, JFR_THREADLOCAL); // Thread local lease for blob creation. // TYPE_THREAD and count is written unconditionally for blobs, also for vthreads. writer.write_type(TYPE_THREAD); writer.write_count(1); @@ -119,7 +120,7 @@ void JfrTypeManager::write_checkpoint(Thread* t, traceid tid /* 0 */, oop vthrea assert(current != NULL, "invariant"); const bool is_vthread = vthread != nullptr; ResourceMark rm(current); - JfrCheckpointWriter writer(current, true, THREADS, !is_vthread); // Virtual Threads use thread local lease. + JfrCheckpointWriter writer(current, true, THREADS, is_vthread ? JFR_VIRTUAL_THREADLOCAL : JFR_THREADLOCAL); if (is_vthread) { // TYPE_THREAD and count is written later as part of vthread bulk serialization. writer.set_count(1); // Only a logical marker for the checkpoint header. @@ -202,7 +203,7 @@ static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer* assert(!types.in_list(registration), "invariant"); DEBUG_ONLY(assert_not_registered_twice(id, types);) if (JfrRecorder::is_recording()) { - JfrCheckpointWriter writer(STATICS); + JfrCheckpointWriter writer(Thread::current(), true, STATICS); registration->invoke(writer); } types.add(registration); diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp index 1471be963f0..25cd473933f 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp @@ -37,7 +37,7 @@ JfrBuffer::JfrBuffer() : _next(NULL), _flags(0), _context(0) {} -bool JfrBuffer::initialize(size_t header_size, size_t size) { +void JfrBuffer::initialize(size_t header_size, size_t size) { assert(_next == NULL, "invariant"); assert(_identity == NULL, "invariant"); _header_size = (u2)header_size; @@ -48,10 +48,9 @@ bool JfrBuffer::initialize(size_t header_size, size_t size) { assert(!transient(), "invariant"); assert(!lease(), "invariant"); assert(!retired(), "invariant"); - return true; } -void JfrBuffer::reinitialize(bool exclusion /* false */) { +void JfrBuffer::reinitialize() { acquire_critical_section_top(); set_pos(start()); release_critical_section_top(start()); @@ -173,8 +172,7 @@ size_t JfrBuffer::unflushed_size() const { enum FLAG { RETIRED = 1, TRANSIENT = 2, - LEASE = 4, - EXCLUDED = 8 + LEASE = 4 }; inline u1 load(const volatile u1* dest) { diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp index 154920c30e2..7ec97a88c61 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp @@ -79,8 +79,8 @@ class JfrBuffer { public: JfrBuffer(); - bool initialize(size_t header_size, size_t size); - void reinitialize(bool exclusion = false); + void initialize(size_t header_size, size_t size); + void reinitialize(); const u1* start() const { return ((const u1*)this) + _header_size; diff --git a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp index 95e6c114efa..f4b226cde9f 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp @@ -218,10 +218,7 @@ inline typename FreeListType::NodePtr JfrMemorySpaceinitialize(sizeof(Node), aligned_size_bytes)) { - JfrCHeapObj::free(node, aligned_size_bytes + sizeof(Node)); - return NULL; - } + node->initialize(sizeof(Node), aligned_size_bytes); return node; } diff --git a/src/hotspot/share/jfr/utilities/jfrTypes.hpp b/src/hotspot/share/jfr/utilities/jfrTypes.hpp index fa43d28fc09..aaf925b1867 100644 --- a/src/hotspot/share/jfr/utilities/jfrTypes.hpp +++ b/src/hotspot/share/jfr/utilities/jfrTypes.hpp @@ -57,4 +57,10 @@ enum JfrCheckpointType { THREADS = 8 }; +enum JfrCheckpointBufferKind { + JFR_GLOBAL, + JFR_THREADLOCAL, + JFR_VIRTUAL_THREADLOCAL +}; + #endif // SHARE_JFR_UTILITIES_JFRTYPES_HPP