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