1 | /* |
2 | * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. |
3 | * |
4 | * This code is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License version 2 only, as |
6 | * published by the Free Software Foundation. |
7 | * |
8 | * This code is distributed in the hope that it will be useful, but WITHOUT |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
11 | * version 2 for more details (a copy is included in the LICENSE file that |
12 | * accompanied this code). |
13 | * |
14 | * You should have received a copy of the GNU General Public License version |
15 | * 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 USA |
19 | * or visit www.oracle.com if you need additional information or have any |
20 | * questions. |
21 | * |
22 | */ |
23 | |
24 | #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP |
25 | #define SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP |
26 | |
27 | #include "memory/allocation.hpp" |
28 | #include "runtime/orderAccess.hpp" |
29 | |
30 | typedef jbyte ShenandoahSharedValue; |
31 | |
32 | // Needed for cooperation with generated code. |
33 | STATIC_ASSERT(sizeof(ShenandoahSharedValue) == 1); |
34 | |
35 | typedef struct ShenandoahSharedFlag { |
36 | enum { |
37 | UNSET = 0, |
38 | SET = 1 |
39 | }; |
40 | |
41 | DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile ShenandoahSharedValue)); |
42 | volatile ShenandoahSharedValue value; |
43 | DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); |
44 | |
45 | ShenandoahSharedFlag() { |
46 | unset(); |
47 | } |
48 | |
49 | void set() { |
50 | OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)SET); |
51 | } |
52 | |
53 | void unset() { |
54 | OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)UNSET); |
55 | } |
56 | |
57 | bool is_set() const { |
58 | return OrderAccess::load_acquire(&value) == SET; |
59 | } |
60 | |
61 | bool is_unset() const { |
62 | return OrderAccess::load_acquire(&value) == UNSET; |
63 | } |
64 | |
65 | void set_cond(bool val) { |
66 | if (val) { |
67 | set(); |
68 | } else { |
69 | unset(); |
70 | } |
71 | } |
72 | |
73 | bool try_set() { |
74 | if (is_set()) { |
75 | return false; |
76 | } |
77 | ShenandoahSharedValue old = Atomic::cmpxchg((ShenandoahSharedValue)SET, &value, (ShenandoahSharedValue)UNSET); |
78 | return old == UNSET; // success |
79 | } |
80 | |
81 | bool try_unset() { |
82 | if (!is_set()) { |
83 | return false; |
84 | } |
85 | ShenandoahSharedValue old = Atomic::cmpxchg((ShenandoahSharedValue)UNSET, &value, (ShenandoahSharedValue)SET); |
86 | return old == SET; // success |
87 | } |
88 | |
89 | volatile ShenandoahSharedValue* addr_of() { |
90 | return &value; |
91 | } |
92 | |
93 | private: |
94 | volatile ShenandoahSharedValue* operator&() { |
95 | fatal("Use addr_of() instead" ); |
96 | return NULL; |
97 | } |
98 | |
99 | bool operator==(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
100 | bool operator!=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
101 | bool operator> (ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
102 | bool operator>=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
103 | bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
104 | bool operator<=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
105 | |
106 | } ShenandoahSharedFlag; |
107 | |
108 | typedef struct ShenandoahSharedBitmap { |
109 | DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile ShenandoahSharedValue)); |
110 | volatile ShenandoahSharedValue value; |
111 | DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); |
112 | |
113 | ShenandoahSharedBitmap() { |
114 | clear(); |
115 | } |
116 | |
117 | void set(uint mask) { |
118 | assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity" ); |
119 | ShenandoahSharedValue mask_val = (ShenandoahSharedValue) mask; |
120 | while (true) { |
121 | ShenandoahSharedValue ov = OrderAccess::load_acquire(&value); |
122 | if ((ov & mask_val) != 0) { |
123 | // already set |
124 | return; |
125 | } |
126 | |
127 | ShenandoahSharedValue nv = ov | mask_val; |
128 | if (Atomic::cmpxchg(nv, &value, ov) == ov) { |
129 | // successfully set |
130 | return; |
131 | } |
132 | } |
133 | } |
134 | |
135 | void unset(uint mask) { |
136 | assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity" ); |
137 | ShenandoahSharedValue mask_val = (ShenandoahSharedValue) mask; |
138 | while (true) { |
139 | ShenandoahSharedValue ov = OrderAccess::load_acquire(&value); |
140 | if ((ov & mask_val) == 0) { |
141 | // already unset |
142 | return; |
143 | } |
144 | |
145 | ShenandoahSharedValue nv = ov & ~mask_val; |
146 | if (Atomic::cmpxchg(nv, &value, ov) == ov) { |
147 | // successfully unset |
148 | return; |
149 | } |
150 | } |
151 | } |
152 | |
153 | void clear() { |
154 | OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)0); |
155 | } |
156 | |
157 | bool is_set(uint mask) const { |
158 | return !is_unset(mask); |
159 | } |
160 | |
161 | bool is_unset(uint mask) const { |
162 | assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity" ); |
163 | return (OrderAccess::load_acquire(&value) & (ShenandoahSharedValue) mask) == 0; |
164 | } |
165 | |
166 | bool is_clear() const { |
167 | return (OrderAccess::load_acquire(&value)) == 0; |
168 | } |
169 | |
170 | void set_cond(uint mask, bool val) { |
171 | if (val) { |
172 | set(mask); |
173 | } else { |
174 | unset(mask); |
175 | } |
176 | } |
177 | |
178 | volatile ShenandoahSharedValue* addr_of() { |
179 | return &value; |
180 | } |
181 | |
182 | ShenandoahSharedValue raw_value() const { |
183 | return value; |
184 | } |
185 | |
186 | private: |
187 | volatile ShenandoahSharedValue* operator&() { |
188 | fatal("Use addr_of() instead" ); |
189 | return NULL; |
190 | } |
191 | |
192 | bool operator==(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
193 | bool operator!=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
194 | bool operator> (ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
195 | bool operator>=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
196 | bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
197 | bool operator<=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead" ); return false; } |
198 | |
199 | } ShenandoahSharedBitmap; |
200 | |
201 | template<class T> |
202 | struct ShenandoahSharedEnumFlag { |
203 | DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile ShenandoahSharedValue)); |
204 | volatile ShenandoahSharedValue value; |
205 | DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); |
206 | |
207 | ShenandoahSharedEnumFlag() { |
208 | value = 0; |
209 | } |
210 | |
211 | void set(T v) { |
212 | assert (v >= 0, "sanity" ); |
213 | assert (v < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity" ); |
214 | OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)v); |
215 | } |
216 | |
217 | T get() const { |
218 | return (T)OrderAccess::load_acquire(&value); |
219 | } |
220 | |
221 | T cmpxchg(T new_value, T expected) { |
222 | assert (new_value >= 0, "sanity" ); |
223 | assert (new_value < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity" ); |
224 | return (T)Atomic::cmpxchg((ShenandoahSharedValue)new_value, &value, (ShenandoahSharedValue)expected); |
225 | } |
226 | |
227 | volatile ShenandoahSharedValue* addr_of() { |
228 | return &value; |
229 | } |
230 | |
231 | private: |
232 | volatile T* operator&() { |
233 | fatal("Use addr_of() instead" ); |
234 | return NULL; |
235 | } |
236 | |
237 | bool operator==(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
238 | bool operator!=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
239 | bool operator> (ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
240 | bool operator>=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
241 | bool operator< (ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
242 | bool operator<=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead" ); return false; } |
243 | |
244 | }; |
245 | |
246 | #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP |
247 | |