Path: blob/master/src/hotspot/share/jfr/utilities/jfrVersionSystem.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_HPP25#define SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_HPP2627/*28* A lock-free data structure usually require support for tracking references29* in the service of Safe Memory Reclamation (SMR). JfrVersionSystem provides local,30* compared to global, reference tracking for an assoicated data structure.31*32* A client, before accessing a structure, will perform a "checkout" from the JfrVersionSystem.33* This checkout is associated with the current, or latest, version, analogous to the "tip" in a version control system.34* When a client is done it releases its checkout, by which the JfrVersionSystem is notified that the client35* is no longer an active user of the associated structure.36*37* If a client performs a modification, it will register this with the JfrVersionSystem, by means of incrementing the current version.38*39* To guarantee safe memory reclamation, say before attempting a delete, a client will use the JfrVersionSystem to40* check for potential active uses, i.e. checkouts, with versions earlier than the version associated with a specific modification.41*42* Let's exemplify this with the removal of a node from a linked-list:43*44* 1. Before accessing the list, the client will check out the latest version from the JfrVersionSystem. This access is now tracked.45* 2. The client finds a node it wants to use, and excises the node from the list.46* 3. This excision is a modification so the client will increment the current version.47* 4. Before it can start to use proper the node just excised, the client must ensure no possible references exist.48* 5. To do this, the client inspects the JfrVersionSystem to possibly await the release of existing checkouts,49* i.e. for versions less than the version associated with the modification.50* 6. On return, the client is guaranteed exclusive access to the excised node.51*52* Tracking the version of a structure is conceptually similar to tracking a representative pointer using Hazard Pointers,53* or by using a global counter or some kind of ticket system.54*55* The implementation was inspired by Andrei Alexandrescu and Maged Michael, Lock-Free Data Structures with Hazard Pointers56* https ://www.drdobbs.com/lock-free-data-structures-with-hazard-po/18440189057*/5859#include "jfr/utilities/jfrAllocation.hpp"60#include "jfr/utilities/jfrRefCountPointer.hpp"61#include "jfr/utilities/jfrTypes.hpp"62#include "memory/padded.hpp"6364class JfrVersionSystem : public JfrCHeapObj {65public:66typedef traceid Type;67private:68class Node : public JfrCHeapObj {69friend class JfrVersionSystem;70template <typename>71friend class RefCountHandle;72private:73JfrVersionSystem* const _system;74Node* _next;75mutable Type _version;76SingleThreadedRefCounter _ref_counter;77mutable bool _live;78Node(JfrVersionSystem* system);79void add_ref() const;80void remove_ref() const;81Type version() const;82void set(Type version) const;83public:84void checkout();85void commit();86const Node* operator->() const { return this; }87Node* operator->() { return this; }88};89typedef Node* NodePtr;9091public:92JfrVersionSystem();93~JfrVersionSystem();94void reset();9596typedef RefCountHandle<Node> Handle;97Handle get();9899private:100NodePtr acquire();101void await(Type version);102Type tip() const;103Type inc_tip();104NodePtr synchronize_with(Type version, NodePtr last) const;105DEBUG_ONLY(void assert_state(const Node* node) const;)106struct PaddedTip {107DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);108volatile Type _value;109DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile Type));110};111PaddedTip _tip;112NodePtr _head;113};114115#endif // SHARE_JFR_UTILITIES_JFRVERSIONSYSTEM_HPP116117118