1/*
2 * Copyright (c) 2012, 2019, 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_RECORDER_STORAGE_JFRBUFFER_HPP
26#define SHARE_JFR_RECORDER_STORAGE_JFRBUFFER_HPP
27
28#include "memory/allocation.hpp"
29
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//
48class 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;
58
59 const u1* stable_top() const;
60
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 }
70
71 JfrBuffer* prev() const {
72 return _prev;
73 }
74
75 void set_next(JfrBuffer* next) {
76 _next = next;
77 }
78
79 void set_prev(JfrBuffer* prev) {
80 _prev = prev;
81 }
82
83 const u1* start() const {
84 return ((const u1*)this) + _header_size;
85 }
86
87 u1* start() {
88 return ((u1*)this) + _header_size;
89 }
90
91 const u1* end() const {
92 return start() + size();
93 }
94
95 const u1* pos() const {
96 return _pos;
97 }
98
99 u1* pos() {
100 return _pos;
101 }
102
103 u1** pos_address() {
104 return (u1**)&_pos;
105 }
106
107 void set_pos(u1* new_pos) {
108 assert(new_pos <= end(), "invariant");
109 _pos = new_pos;
110 }
111
112 void set_pos(size_t size) {
113 assert(_pos + size <= end(), "invariant");
114 _pos += size;
115 }
116
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);
121
122 size_t header_size() const {
123 return _header_size;
124 }
125
126 size_t size() const {
127 return _size * BytesPerWord;
128 }
129
130 size_t total_size() const {
131 return header_size() + size();
132 }
133
134 size_t free_size() const {
135 return end() - pos();
136 }
137
138 size_t unflushed_size() const;
139
140 bool empty() const {
141 return pos() == start();
142 }
143
144 const void* identity() const {
145 return _identity;
146 }
147
148 void acquire(const void* id);
149 bool try_acquire(const void* id);
150 bool acquired_by(const void* id) const;
151 bool acquired_by_self() const;
152 void release();
153
154 void move(JfrBuffer* const to, size_t size);
155 void concurrent_move_and_reinitialize(JfrBuffer* const to, size_t size);
156
157 bool transient() const;
158 void set_transient();
159 void clear_transient();
160
161 bool lease() const;
162 void set_lease();
163 void clear_lease();
164
165 bool retired() const;
166 void set_retired();
167 void clear_retired();
168};
169
170class JfrAgeNode : public JfrBuffer {
171 private:
172 JfrBuffer* _retired;
173
174 public:
175 JfrAgeNode() : _retired(NULL) {}
176 void set_retired_buffer(JfrBuffer* retired) {
177 _retired = retired;
178 }
179 JfrBuffer* retired_buffer() const {
180 return _retired;
181 }
182};
183
184#endif // SHARE_JFR_RECORDER_STORAGE_JFRBUFFER_HPP
185