Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/jfr/utilities/jfrConcurrentLinkedListHost.hpp
41149 views
1
/*
2
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#ifndef SHARE_JFR_UTILITIES_JFRCONCURRENTLINKEDLISTHOST_HPP
26
#define SHARE_JFR_UTILITIES_JFRCONCURRENTLINKEDLISTHOST_HPP
27
28
#include "jfr/utilities/jfrAllocation.hpp"
29
30
/*
31
* This implementation is a derivation from Harris
32
* https://www.cl.cam.ac.uk/research/srg/netos/papers/2001-caslists.pdf
33
*
34
* A concurrent LIFO structure can be built using the pair:
35
*
36
* insert_head() and remove()
37
*
38
* The LIFO algorithm is non-blocking, more specifically wait-free.
39
* When combined with a system for safe memory reclamation, where a thread will require
40
* to know if other threads are possibly reading the memory that is to be reclaimed (more below),
41
* a potential wait point is introduced, so technically, we are no longer wait-free.
42
* The combination is still lock-free, but since it is no longer pure non-blocking,
43
* we instead say the solution is concurrent.
44
*
45
* It is also possible to build a FIFO structure using the pair:
46
*
47
* insert_tail() and remove()
48
*
49
* To allow FIFO, the solution extends support to mark, or reserve a node, not only as part of deletions
50
* as with the LIFO case, but also, to enable tail insertions.
51
*
52
* Compared to the LIFO algorithm, the FIFO algorithm is not non-blocking, because inserts to the tail block,
53
* making it not lock-free. remove() is lock-free up until the last node in the list. In practice, the FIFO
54
* solution can be used in certain ways that very closely approximate non-blocking, for example, situations
55
* involving a single producer and multiple consumers.
56
*
57
* Although the FIFO algorithm is not non-blocking, it includes an optimization for remove() that is attractive:
58
* In the LIFO case, a slow path taken as the result of a failed excision would have to re-traverse the list
59
* to find the updated adjacent node pair for the already marked node. However, that node might already have
60
* been excised by some other thread, letting the thread potentially traverse the entire list just to discover
61
* it is no longer present (not an issue if the list is ordered by a key, then traversal is only to node >= key).
62
* In the FIFO case, premised on the invariant that inserts only come in from the tail, it is possible to prove
63
* a failed cas not to be the result of a new node inserted as with the LIFO case. With FIFO, there is only a single
64
* failure mode, i.e. some other thread excised the node already. Therefore, in the FIFO case, we skip the slow-path search pass.
65
*
66
* We say that the FIFO solution is "mostly" concurrent, in certain situations.
67
*
68
* Safe memory reclamation is based on a reference tracking scheme based on versioning, implemented using JfrVersionSystem.
69
* An access to the list is "versioned", with clients checking out the latest version describing the list.
70
* Destructive modifications made by clients, i.e. deletions, are signalled by incrementing the version.
71
* Before reclamation, a client inspects JfrVersionSystem to ensure checkouts with versions strictly
72
* less than the version of the modification have been relinquished. See utilities/JfrVersionSystem.hpp.
73
*
74
* Insertions can only take place from one end of the list, head or tail, exclusively.
75
* Specializations, a.k.a clients, must ensure this requirement.
76
*/
77
78
template <typename Client, template <typename> class SearchPolicy, typename AllocPolicy = JfrCHeapObj>
79
class JfrConcurrentLinkedListHost : public AllocPolicy {
80
private:
81
Client* _client;
82
typedef typename Client::Node Node;
83
typedef Node* NodePtr;
84
typedef const Node* ConstNodePtr;
85
typedef typename Client::VersionSystem::Type VersionType;
86
typedef typename Client::VersionSystem::Handle VersionHandle;
87
public:
88
JfrConcurrentLinkedListHost(Client* client);
89
bool initialize();
90
void insert_head(NodePtr node, NodePtr head, ConstNodePtr tail) const;
91
void insert_tail(NodePtr node, NodePtr head, NodePtr last, ConstNodePtr tail) const;
92
NodePtr remove(NodePtr head, ConstNodePtr tail, NodePtr last = NULL, bool insert_is_head = true);
93
template <typename Callback>
94
void iterate(NodePtr head, ConstNodePtr tail, Callback& cb);
95
bool in_list(ConstNodePtr node, NodePtr head, ConstNodePtr tail) const;
96
};
97
98
#endif // SHARE_JFR_UTILITIES_JFRCONCURRENTLINKEDLISTHOST_HPP
99
100