diff --git a/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index dd41da014fc6811ab2797293da4fafa1551aa6cc..69a4ccfef8dd74194bafee8492fe92a3a8bbad96 100644 --- a/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,6 +135,8 @@ void JfrCheckpointManager::register_service_thread(const Thread* thread) { void JfrCheckpointManager::register_full(BufferPtr t, Thread* thread) { // nothing here at the moment + assert(t != NULL, "invariant"); + assert(t->acquired_by(thread), "invariant"); assert(t->retired(), "invariant"); } diff --git a/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp b/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp index cf4f33e18c4b2a05ecbffb9787cd89bc3509dba5..120ea38c44943da10f34450870835d9d6dec948c 100644 --- a/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp +++ b/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,6 +137,14 @@ void JfrBuffer::clear_identity() { _identity = NULL; } +bool JfrBuffer::acquired_by(const void* id) const { + return identity() == id; +} + +bool JfrBuffer::acquired_by_self() const { + return acquired_by(Thread::current()); +} + #ifdef ASSERT static bool validate_to(const JfrBuffer* const to, size_t size) { assert(to != NULL, "invariant"); @@ -154,10 +162,6 @@ static bool validate_this(const JfrBuffer* const t, size_t size) { assert(t->top() + size <= t->pos(), "invariant"); return true; } - -bool JfrBuffer::acquired_by_self() const { - return identity() == Thread::current(); -} #endif // ASSERT void JfrBuffer::move(JfrBuffer* const to, size_t size) { @@ -184,7 +188,6 @@ void JfrBuffer::concurrent_move_and_reinitialize(JfrBuffer* const to, size_t siz set_concurrent_top(start()); } -// flags enum FLAG { RETIRED = 1, TRANSIENT = 2, diff --git a/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp b/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp index 5e28e23aabea1e8644640b42aa2e78b743b761d0..f97d50fabae801623b25e4a762fc534afb029662 100644 --- a/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp +++ b/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp @@ -57,7 +57,6 @@ class JfrBuffer { u4 _size; const u1* stable_top() const; - void clear_flags(); public: JfrBuffer(); @@ -150,6 +149,8 @@ class JfrBuffer { void acquire(const void* id); bool try_acquire(const void* id); + bool acquired_by(const void* id) const; + bool acquired_by_self() const; void release(); void move(JfrBuffer* const to, size_t size); @@ -166,8 +167,6 @@ class JfrBuffer { bool retired() const; void set_retired(); void clear_retired(); - - debug_only(bool acquired_by_self() const;) }; class JfrAgeNode : public JfrBuffer { diff --git a/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp index c106e02a8b0d44dd8bf78adbd9bc2f001af7ed9a..2acf453c43afd662e41a1335061b0f8079c99c46 100644 --- a/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp +++ b/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp @@ -346,19 +346,19 @@ inline void process_free_list(Processor& processor, Mspace* mspace, jfr_iter_dir template inline bool ReleaseOp::process(typename Mspace::Type* t) { assert(t != NULL, "invariant"); - if (t->retired() || t->try_acquire(_thread)) { - if (t->transient()) { - if (_release_full) { - mspace_release_full_critical(t, _mspace); - } else { - mspace_release_free_critical(t, _mspace); - } - return true; + // assumes some means of exclusive access to t + if (t->transient()) { + if (_release_full) { + mspace_release_full_critical(t, _mspace); + } else { + mspace_release_free_critical(t, _mspace); } - t->reinitialize(); - assert(t->empty(), "invariant"); - t->release(); // publish + return true; } + t->reinitialize(); + assert(t->empty(), "invariant"); + assert(!t->retired(), "invariant"); + t->release(); // publish return true; } diff --git a/src/share/vm/jfr/recorder/storage/jfrStorage.cpp b/src/share/vm/jfr/recorder/storage/jfrStorage.cpp index 3503d986f23aad6dcf0659bffb7f28ee66fb85b8..23a106702a686ee676eab003fcbb7d541e5c6c1d 100644 --- a/src/share/vm/jfr/recorder/storage/jfrStorage.cpp +++ b/src/share/vm/jfr/recorder/storage/jfrStorage.cpp @@ -340,9 +340,9 @@ static bool full_buffer_registration(BufferPtr buffer, JfrStorageAgeMspace* age_ void JfrStorage::register_full(BufferPtr buffer, Thread* thread) { assert(buffer != NULL, "invariant"); assert(buffer->retired(), "invariant"); + assert(buffer->acquired_by(thread), "invariant"); if (!full_buffer_registration(buffer, _age_mspace, control(), thread)) { handle_registration_failure(buffer); - buffer->release(); } if (control().should_post_buffer_full_message()) { _post_box.post(MSG_FULLBUFFER); @@ -377,8 +377,8 @@ void JfrStorage::release(BufferPtr buffer, Thread* thread) { } } assert(buffer->empty(), "invariant"); + assert(buffer->identity() != NULL, "invariant"); control().increment_dead(); - buffer->release(); buffer->set_retired(); } @@ -733,13 +733,14 @@ public: Scavenger(JfrStorageControl& control, Mspace* mspace) : _control(control), _mspace(mspace), _count(0), _amount(0) {} bool process(Type* t) { if (t->retired()) { + assert(t->identity() != NULL, "invariant"); + assert(t->empty(), "invariant"); assert(!t->transient(), "invariant"); assert(!t->lease(), "invariant"); - assert(t->empty(), "invariant"); - assert(t->identity() == NULL, "invariant"); ++_count; _amount += t->total_size(); t->clear_retired(); + t->release(); _control.decrement_dead(); mspace_release_full_critical(t, _mspace); } diff --git a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp index 5a54bd0e6c5b4a9380bfa025934c14104aece5df..1f4428da56ea7820b79a9dd0e9bcbc8a1bd486ad 100644 --- a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp +++ b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp @@ -92,7 +92,6 @@ class ConcurrentWriteOpExcludeRetired : private ConcurrentWriteOp { size_t processed() const { return ConcurrentWriteOp::processed(); } }; - template class MutexedWriteOp { private: @@ -104,6 +103,15 @@ class MutexedWriteOp { size_t processed() const { return _operation.processed(); } }; +template +class ExclusiveOp : private MutexedWriteOp { + public: + typedef typename Operation::Type Type; + ExclusiveOp(Operation& operation) : MutexedWriteOp(operation) {} + bool process(Type* t); + size_t processed() const { return MutexedWriteOp::processed(); } +}; + enum jfr_operation_mode { mutexed = 1, concurrent diff --git a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp index f23b024f8dca0edeeb6f0c891a7cb2ae9ed1140f..620a9f2614be33c978100f1bca2a399ddd81f9b8 100644 --- a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp +++ b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP #include "jfr/recorder/storage/jfrStorageUtils.hpp" +#include "runtime/thread.inline.hpp" template inline bool UnBufferedWriteToChunk::write(T* t, const u1* data, size_t size) { @@ -75,6 +76,28 @@ inline bool MutexedWriteOp::process(typename Operation::Type* t) { return result; } +template +static void retired_sensitive_acquire(Type* t) { + assert(t != NULL, "invariant"); + if (t->retired()) { + return; + } + Thread* const thread = Thread::current(); + while (!t->try_acquire(thread)) { + if (t->retired()) { + return; + } + } +} + +template +inline bool ExclusiveOp::process(typename Operation::Type* t) { + retired_sensitive_acquire(t); + assert(t->acquired_by_self() || t->retired(), "invariant"); + // User is required to ensure proper release of the acquisition + return MutexedWriteOp::process(t); +} + template inline bool DiscardOp::process(typename Operation::Type* t) { assert(t != NULL, "invariant"); diff --git a/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp b/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp index f650db5c8277f85ee4e69e5c121bf6901ea0055a..105089b050d1ce584b6b01cdcd4310e124f48148 100644 --- a/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp +++ b/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,93 +139,76 @@ bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) { return current_epoch; } -class StringPoolWriteOp { +template