Path: blob/master/src/hotspot/share/jfr/utilities/jfrVersionSystem.inline.hpp
41149 views
/*1* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_INLINE_HPP25#define SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_INLINE_HPP2627#include "jfr/utilities/jfrVersionSystem.hpp"2829#include "runtime/atomic.hpp"30#include "runtime/os.hpp"3132inline JfrVersionSystem::JfrVersionSystem() : _tip(), _head(NULL) {33_tip._value = 1;34}3536inline JfrVersionSystem::~JfrVersionSystem() {37reset();38}3940inline void JfrVersionSystem::reset() {41NodePtr node = _head;42while (node != NULL) {43NodePtr next = node->_next;44delete node;45node = next;46}47_head = NULL;48_tip._value = 1;49}5051inline JfrVersionSystem::Type JfrVersionSystem::tip() const {52return Atomic::load(&_tip._value);53}5455inline JfrVersionSystem::Type JfrVersionSystem::inc_tip() {56traceid cmp;57traceid xchg;58do {59cmp = _tip._value;60xchg = cmp + 1;61} while (Atomic::cmpxchg(&_tip._value, cmp, xchg) != cmp);62return xchg;63}6465inline JfrVersionSystem::NodePtr JfrVersionSystem::acquire() {66NodePtr node = _head;67// free68while (node != NULL) {69if (node->_live || Atomic::cmpxchg(&node->_live, false, true)) {70node = node->_next;71continue;72}73DEBUG_ONLY(assert_state(node);)74return node;75}76// new77node = new Node(this);78NodePtr next;79do {80next = _head;81node->_next = next;82} while (Atomic::cmpxchg(&_head, next, node) != next);83DEBUG_ONLY(assert_state(node);)84return node;85}8687inline JfrVersionSystem::Handle JfrVersionSystem::get() {88return Handle::make(acquire());89}9091inline JfrVersionSystem::Node::Node(JfrVersionSystem* system) : _system(system), _next(NULL), _version(0), _live(true) {}9293inline traceid JfrVersionSystem::Node::version() const {94return _version;95}9697inline void JfrVersionSystem::Node::set(traceid version) const {98Atomic::release_store_fence(&_version, version);99}100101inline void JfrVersionSystem::Node::add_ref() const {102_ref_counter.inc();103}104105inline void JfrVersionSystem::Node::remove_ref() const {106if (_ref_counter.dec()) {107assert(_live, "invariant");108set(0);109_live = false;110}111}112113inline void JfrVersionSystem::Node::checkout() {114set(_system->tip());115assert(version() != 0, "invariant");116}117118inline void JfrVersionSystem::Node::commit() {119assert(version() != 0, "invariant");120// A commit consist of an atomic increment of the tip.121const Type commit_version = _system->inc_tip();122// Release this checkout.123set(0);124// Await release of checkouts for earlier versions.125_system->await(commit_version);126}127128inline JfrVersionSystem::NodePtr129JfrVersionSystem::synchronize_with(JfrVersionSystem::Type version, JfrVersionSystem::NodePtr node) const {130assert(version <= tip(), "invariant");131while (node != NULL) {132const Type checkedout = Atomic::load_acquire(&node->_version);133if (checkedout > 0 && checkedout < version) {134return node;135}136node = node->_next;137}138return NULL;139}140141inline void JfrVersionSystem::await(JfrVersionSystem::Type version) {142assert(version > 0, "invariant");143static const int backoff_unit_ns = 10;144int backoff_factor = 1;145NodePtr last = _head;146while (true) {147last = synchronize_with(version, last);148if (last == NULL) {149return;150}151os::naked_short_nanosleep(backoff_unit_ns * backoff_factor++);152}153}154155#ifdef ASSERT156inline void JfrVersionSystem::assert_state(const JfrVersionSystem::Node* node) const {157assert(node != NULL, "invariant");158assert(node->_live, "invariant");159assert(node->_version == 0, "invariant");160assert(node->_ref_counter.current() == 0, "invariant");161}162#endif // ASSERT163164#endif // SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_INLINE_HPP165166167