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 "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 ShenandoahSharedFlagShenandoahSharedFlag45 ShenandoahSharedFlag() { 46 unset(); 47 } 48 setShenandoahSharedFlag49 void set() { 50 OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)SET); 51 } 52 unsetShenandoahSharedFlag53 void unset() { 54 OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)UNSET); 55 } 56 is_setShenandoahSharedFlag57 bool is_set() const { 58 return OrderAccess::load_acquire(&value) == SET; 59 } 60 is_unsetShenandoahSharedFlag61 bool is_unset() const { 62 return OrderAccess::load_acquire(&value) == UNSET; 63 } 64 set_condShenandoahSharedFlag65 void set_cond(bool val) { 66 if (val) { 67 set(); 68 } else { 69 unset(); 70 } 71 } 72 try_setShenandoahSharedFlag73 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 try_unsetShenandoahSharedFlag81 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 addr_ofShenandoahSharedFlag89 volatile ShenandoahSharedValue* addr_of() { 90 return &value; 91 } 92 93 private: operator &ShenandoahSharedFlag94 volatile ShenandoahSharedValue* operator&() { 95 fatal("Use addr_of() instead"); 96 return NULL; 97 } 98 operator ==ShenandoahSharedFlag99 bool operator==(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator !=ShenandoahSharedFlag100 bool operator!=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator >ShenandoahSharedFlag101 bool operator> (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator >=ShenandoahSharedFlag102 bool operator>=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator <ShenandoahSharedFlag103 bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator <=ShenandoahSharedFlag104 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 ShenandoahSharedBitmapShenandoahSharedBitmap113 ShenandoahSharedBitmap() { 114 clear(); 115 } 116 setShenandoahSharedBitmap117 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 unsetShenandoahSharedBitmap135 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 clearShenandoahSharedBitmap153 void clear() { 154 OrderAccess::release_store_fence(&value, (ShenandoahSharedValue)0); 155 } 156 is_setShenandoahSharedBitmap157 bool is_set(uint mask) const { 158 return !is_unset(mask); 159 } 160 is_unsetShenandoahSharedBitmap161 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 is_clearShenandoahSharedBitmap166 bool is_clear() const { 167 return (OrderAccess::load_acquire(&value)) == 0; 168 } 169 set_condShenandoahSharedBitmap170 void set_cond(uint mask, bool val) { 171 if (val) { 172 set(mask); 173 } else { 174 unset(mask); 175 } 176 } 177 addr_ofShenandoahSharedBitmap178 volatile ShenandoahSharedValue* addr_of() { 179 return &value; 180 } 181 raw_valueShenandoahSharedBitmap182 ShenandoahSharedValue raw_value() const { 183 return value; 184 } 185 186 private: operator &ShenandoahSharedBitmap187 volatile ShenandoahSharedValue* operator&() { 188 fatal("Use addr_of() instead"); 189 return NULL; 190 } 191 operator ==ShenandoahSharedBitmap192 bool operator==(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator !=ShenandoahSharedBitmap193 bool operator!=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator >ShenandoahSharedBitmap194 bool operator> (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator >=ShenandoahSharedBitmap195 bool operator>=(ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator <ShenandoahSharedBitmap196 bool operator< (ShenandoahSharedFlag& other) { fatal("Use is_set() instead"); return false; } operator <=ShenandoahSharedBitmap197 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 ShenandoahSharedEnumFlagShenandoahSharedEnumFlag207 ShenandoahSharedEnumFlag() { 208 value = 0; 209 } 210 setShenandoahSharedEnumFlag211 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 getShenandoahSharedEnumFlag217 T get() const { 218 return (T)OrderAccess::load_acquire(&value); 219 } 220 cmpxchgShenandoahSharedEnumFlag221 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 addr_ofShenandoahSharedEnumFlag227 volatile ShenandoahSharedValue* addr_of() { 228 return &value; 229 } 230 231 private: operator &ShenandoahSharedEnumFlag232 volatile T* operator&() { 233 fatal("Use addr_of() instead"); 234 return NULL; 235 } 236 operator ==ShenandoahSharedEnumFlag237 bool operator==(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } operator !=ShenandoahSharedEnumFlag238 bool operator!=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } operator >ShenandoahSharedEnumFlag239 bool operator> (ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } operator >=ShenandoahSharedEnumFlag240 bool operator>=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } operator <ShenandoahSharedEnumFlag241 bool operator< (ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } operator <=ShenandoahSharedEnumFlag242 bool operator<=(ShenandoahSharedEnumFlag& other) { fatal("Use get() instead"); return false; } 243 244 }; 245 246 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHSHAREDFLAG_HPP 247