8293864: Kitchensink24HStress.java fails with SIGSEGV in JfrCheckpointManager::lease

Reviewed-by: egahlin
This commit is contained in:
Markus Grönlund 2022-10-10 12:39:10 +00:00
parent c5f462e83b
commit 35d17a00ab
9 changed files with 173 additions and 117 deletions

View File

@ -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<JfrCheckpointBufferKind>(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 <typename T>
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<JfrCheckpointManager::Buffer> WriteOperation;
typedef ThreadLocalCheckpointWriteOp<JfrCheckpointManager::Buffer> ThreadLocalCheckpointOperation;
typedef MutexedWriteOp<ThreadLocalCheckpointOperation> ThreadLocalWriteOperation;
typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
typedef ReleaseWithExcisionOp<JfrCheckpointMspace, JfrCheckpointMspace::LiveList> ReleaseOperation;
typedef ExclusiveOp<WriteOperation> GlobalWriteOperation;
typedef CompositeOperation<GlobalWriteOperation, ReleaseOperation> GlobalWriteReleaseOperation;
typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> WriteReleaseOperation;
typedef VirtualThreadLocalCheckpointWriteOp<JfrCheckpointManager::Buffer> VirtualThreadLocalCheckpointOperation;
typedef MutexedWriteOp<VirtualThreadLocalCheckpointOperation> 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<DefaultDiscarder<JfrCheckpointManager::Buffer> > ThreadLocalDiscardOperation;
typedef ExclusiveDiscardOp<DefaultDiscarder<JfrCheckpointManager::Buffer> > GlobalDiscardOperation;
typedef CompositeOperation<GlobalDiscardOperation, ReleaseOperation> DiscardReleaseOperation;
typedef DiscardOp<DefaultDiscarder<JfrCheckpointManager::Buffer> > DiscardOperation;
typedef CompositeOperation<DiscardOperation, ReleaseOperation> 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;
}

View File

@ -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();

View File

@ -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),

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -218,10 +218,7 @@ inline typename FreeListType::NodePtr JfrMemorySpace<Client, RetrievalPolicy, Fr
}
NodePtr node = new (allocation) Node();
assert(node != NULL, "invariant");
if (!node->initialize(sizeof(Node), aligned_size_bytes)) {
JfrCHeapObj::free(node, aligned_size_bytes + sizeof(Node));
return NULL;
}
node->initialize(sizeof(Node), aligned_size_bytes);
return node;
}

View File

@ -57,4 +57,10 @@ enum JfrCheckpointType {
THREADS = 8
};
enum JfrCheckpointBufferKind {
JFR_GLOBAL,
JFR_THREADLOCAL,
JFR_VIRTUAL_THREADLOCAL
};
#endif // SHARE_JFR_UTILITIES_JFRTYPES_HPP