1 /* 2 * Copyright (c) 2017, 2019, Red Hat, Inc. 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_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP 27 28 #include "gc/shenandoah/shenandoahPadding.hpp" 29 #include "memory/allocation.hpp" 30 #include "runtime/atomic.hpp" 31 32 typedef jbyte ShenandoahSharedValue; 33 34 // Needed for cooperation with generated code. 35 STATIC_ASSERT(sizeof(ShenandoahSharedValue) == 1); 36 37 typedef struct ShenandoahSharedFlag { 38 enum { 39 UNSET = 0, 40 SET = 1 41 }; 42 43 shenandoah_padding(0); 44 volatile ShenandoahSharedValue value; 45 shenandoah_padding(1); 46 47 ShenandoahSharedFlag() { 48 unset(); 49 } 50 51 void set() { 52 Atomic::release_store_fence(&value, (ShenandoahSharedValue)SET); 53 } 54 55 void unset() { 56 Atomic::release_store_fence(&value, (ShenandoahSharedValue)UNSET); 57 } 58 59 bool is_set() const { 60 return Atomic::load_acquire(&value) == SET; 61 } 62 63 bool is_unset() const { 64 return Atomic::load_acquire(&value) == UNSET; 65 } 66 67 void set_cond(bool val) { 68 if (val) { 69 set(); 70 } else { 71 unset(); 72 } 73 } 74 75 bool try_set() { 76 if (is_set()) { 77 return false; 78 } 79 ShenandoahSharedValue old = Atomic::cmpxchg(&value, (ShenandoahSharedValue)UNSET, (ShenandoahSharedValue)SET); 80 return old == UNSET; // success 81 } 82 83 bool try_unset() { 84 if (!is_set()) { 85 return false; 86 } 87 ShenandoahSharedValue old = Atomic::cmpxchg(&value, (ShenandoahSharedValue)SET, (ShenandoahSharedValue)UNSET); 88 return old == SET; // success 89 } 90 91 volatile ShenandoahSharedValue* addr_of() { 92 return &value; 93 } 94 95 private: 96 volatile ShenandoahSharedValue* operator&() { 97 fatal("Use addr_of() instead"); 98 return nullptr; 99 } 100 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 bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } 106 bool operator<=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } 107 108 } ShenandoahSharedFlag; 109 110 typedef struct ShenandoahSharedBitmap { 111 shenandoah_padding(0); 112 volatile ShenandoahSharedValue value; 113 shenandoah_padding(1); 114 115 ShenandoahSharedBitmap() { 116 clear(); 117 } 118 119 void set(uint mask) { 120 assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity"); 121 ShenandoahSharedValue mask_val = (ShenandoahSharedValue) mask; 122 while (true) { 123 ShenandoahSharedValue ov = Atomic::load_acquire(&value); 124 if ((ov & mask_val) != 0) { 125 // already set 126 return; 127 } 128 129 ShenandoahSharedValue nv = ov | mask_val; 130 if (Atomic::cmpxchg(&value, ov, nv) == ov) { 131 // successfully set 132 return; 133 } 134 } 135 } 136 137 void unset(uint mask) { 138 assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity"); 139 ShenandoahSharedValue mask_val = (ShenandoahSharedValue) mask; 140 while (true) { 141 ShenandoahSharedValue ov = Atomic::load_acquire(&value); 142 if ((ov & mask_val) == 0) { 143 // already unset 144 return; 145 } 146 147 ShenandoahSharedValue nv = ov & ~mask_val; 148 if (Atomic::cmpxchg(&value, ov, nv) == ov) { 149 // successfully unset 150 return; 151 } 152 } 153 } 154 155 void clear() { 156 Atomic::release_store_fence(&value, (ShenandoahSharedValue)0); 157 } 158 159 bool is_set(uint mask) const { 160 return !is_unset(mask); 161 } 162 163 bool is_unset(uint mask) const { 164 assert (mask < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity"); 165 return (Atomic::load_acquire(&value) & (ShenandoahSharedValue) mask) == 0; 166 } 167 168 bool is_clear() const { 169 return (Atomic::load_acquire(&value)) == 0; 170 } 171 172 void set_cond(uint mask, bool val) { 173 if (val) { 174 set(mask); 175 } else { 176 unset(mask); 177 } 178 } 179 180 volatile ShenandoahSharedValue* addr_of() { 181 return &value; 182 } 183 184 ShenandoahSharedValue raw_value() const { 185 return value; 186 } 187 188 private: 189 volatile ShenandoahSharedValue* operator&() { 190 fatal("Use addr_of() instead"); 191 return nullptr; 192 } 193 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 bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } 199 bool operator<=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } 200 201 } ShenandoahSharedBitmap; 202 203 template<class T> 204 struct ShenandoahSharedEnumFlag { 205 shenandoah_padding(0); 206 volatile ShenandoahSharedValue value; 207 shenandoah_padding(1); 208 209 ShenandoahSharedEnumFlag() { 210 value = 0; 211 } 212 213 void set(T v) { 214 assert (v >= 0, "sanity"); 215 assert (v < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity"); 216 Atomic::release_store_fence(&value, (ShenandoahSharedValue)v); 217 } 218 219 T get() const { 220 return (T)Atomic::load_acquire(&value); 221 } 222 223 T cmpxchg(T new_value, T expected) { 224 assert (new_value >= 0, "sanity"); 225 assert (new_value < (sizeof(ShenandoahSharedValue) * CHAR_MAX), "sanity"); 226 return (T)Atomic::cmpxchg(&value, (ShenandoahSharedValue)expected, (ShenandoahSharedValue)new_value); 227 } 228 229 volatile ShenandoahSharedValue* addr_of() { 230 return &value; 231 } 232 233 private: 234 volatile T* operator&() { 235 fatal("Use addr_of() instead"); 236 return nullptr; 237 } 238 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 bool operator< (ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } 244 bool operator<=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } 245 246 }; 247 248 typedef struct ShenandoahSharedSemaphore { 249 shenandoah_padding(0); 250 volatile ShenandoahSharedValue value; 251 shenandoah_padding(1); 252 253 static uint max_tokens() { 254 return sizeof(ShenandoahSharedValue) * CHAR_MAX; 255 } 256 257 ShenandoahSharedSemaphore(uint tokens) { 258 assert(tokens <= max_tokens(), "sanity"); 259 Atomic::release_store_fence(&value, (ShenandoahSharedValue)tokens); 260 } 261 262 bool try_acquire() { 263 while (true) { 264 ShenandoahSharedValue ov = Atomic::load_acquire(&value); 265 if (ov == 0) { 266 return false; 267 } 268 ShenandoahSharedValue nv = ov - 1; 269 if (Atomic::cmpxchg(&value, ov, nv) == ov) { 270 // successfully set 271 return true; 272 } 273 } 274 } 275 276 void claim_all() { 277 Atomic::release_store_fence(&value, (ShenandoahSharedValue)0); 278 } 279 280 } ShenandoahSharedSemaphore; 281 282 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP