Wed, 17 Jun 2020 11:43:05 +0300
8220293: Deadlock in JFR string pool
Reviewed-by: rehn, egahlin
1 /*
2 * Copyright (c) 2012, 2018, 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 */
25 #ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRBUFFER_HPP
26 #define SHARE_VM_JFR_RECORDER_STORAGE_JFRBUFFER_HPP
28 #include "memory/allocation.hpp"
30 //
31 // Represents a piece of committed memory.
32 //
33 // u1* _pos <-- next store position
34 // u1* _top <-- next unflushed position
35 //
36 // const void* _identity <-- acquired by
37 //
38 // Must be the owner before attempting stores.
39 // Use acquire() and/or try_acquire() for exclusive access
40 // to the (entire) buffer (cas identity).
41 //
42 // Stores to the buffer should uphold transactional semantics.
43 // A new _pos must be updated only after all intended stores have completed.
44 // The relation between _pos and _top must hold atomically,
45 // e.g. the delta must always be fully parsable.
46 // _top can move concurrently by other threads but is always <= _pos.
47 //
48 class JfrBuffer {
49 private:
50 JfrBuffer* _next;
51 JfrBuffer* _prev;
52 const void* volatile _identity;
53 u1* _pos;
54 mutable const u1* volatile _top;
55 u2 _flags;
56 u2 _header_size;
57 u4 _size;
59 const u1* stable_top() const;
61 public:
62 JfrBuffer();
63 bool initialize(size_t header_size, size_t size, const void* id = NULL);
64 void reinitialize();
65 void concurrent_reinitialization();
66 size_t discard();
67 JfrBuffer* next() const {
68 return _next;
69 }
71 JfrBuffer* prev() const {
72 return _prev;
73 }
75 void set_next(JfrBuffer* next) {
76 _next = next;
77 }
79 void set_prev(JfrBuffer* prev) {
80 _prev = prev;
81 }
83 const u1* start() const {
84 return ((const u1*)this) + _header_size;
85 }
87 u1* start() {
88 return ((u1*)this) + _header_size;
89 }
91 const u1* end() const {
92 return start() + size();
93 }
95 const u1* pos() const {
96 return _pos;
97 }
99 u1* pos() {
100 return _pos;
101 }
103 u1** pos_address() {
104 return (u1**)&_pos;
105 }
107 void set_pos(u1* new_pos) {
108 assert(new_pos <= end(), "invariant");
109 _pos = new_pos;
110 }
112 void set_pos(size_t size) {
113 assert(_pos + size <= end(), "invariant");
114 _pos += size;
115 }
117 const u1* top() const;
118 void set_top(const u1* new_top);
119 const u1* concurrent_top() const;
120 void set_concurrent_top(const u1* new_top);
122 size_t header_size() const {
123 return _header_size;
124 }
126 size_t size() const {
127 return _size * BytesPerWord;
128 }
130 size_t total_size() const {
131 return header_size() + size();
132 }
134 size_t free_size() const {
135 return end() - pos();
136 }
138 size_t unflushed_size() const;
140 bool empty() const {
141 return pos() == start();
142 }
144 const void* identity() const {
145 return _identity;
146 }
148 void clear_identity();
150 void acquire(const void* id);
151 bool try_acquire(const void* id);
152 bool acquired_by(const void* id) const;
153 bool acquired_by_self() const;
154 void release();
156 void move(JfrBuffer* const to, size_t size);
157 void concurrent_move_and_reinitialize(JfrBuffer* const to, size_t size);
159 bool transient() const;
160 void set_transient();
161 void clear_transient();
163 bool lease() const;
164 void set_lease();
165 void clear_lease();
167 bool retired() const;
168 void set_retired();
169 void clear_retired();
170 };
172 class JfrAgeNode : public JfrBuffer {
173 private:
174 JfrBuffer* _retired;
176 public:
177 JfrAgeNode() : _retired(NULL) {}
178 void set_retired_buffer(JfrBuffer* retired) {
179 _retired = retired;
180 }
181 JfrBuffer* retired_buffer() const {
182 return _retired;
183 }
184 };
186 #endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRBUFFER_HPP