1 1.1 mrg /* Macros for atomic functionality for tile. 2 1.10 mrg Copyright (C) 2011-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Walter Lee (walt (at) tilera.com) 4 1.1 mrg 5 1.1 mrg This file is free software; you can redistribute it and/or modify it 6 1.1 mrg under the terms of the GNU General Public License as published by the 7 1.1 mrg Free Software Foundation; either version 3, or (at your option) any 8 1.1 mrg later version. 9 1.1 mrg 10 1.1 mrg This file is distributed in the hope that it will be useful, but 11 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 12 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 1.1 mrg General Public License for more details. 14 1.1 mrg 15 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 16 1.1 mrg permissions described in the GCC Runtime Library Exception, version 17 1.1 mrg 3.1, as published by the Free Software Foundation. 18 1.1 mrg 19 1.1 mrg You should have received a copy of the GNU General Public License and 20 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 21 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 1.1 mrg <http://www.gnu.org/licenses/>. */ 23 1.1 mrg 24 1.1 mrg 25 1.1 mrg /* Provides macros for common atomic functionality. */ 26 1.1 mrg 27 1.1 mrg #ifndef _ATOMIC_H_ 28 1.1 mrg #define _ATOMIC_H_ 29 1.1 mrg 30 1.1 mrg #ifdef __tilegx__ 31 1.1 mrg /* Atomic instruction macros 32 1.1 mrg 33 1.1 mrg The macros provided by atomic.h simplify access to the TILE-Gx 34 1.1 mrg architecture's atomic instructions. The architecture provides a 35 1.1 mrg variety of atomic instructions, including "exchange", "compare and 36 1.1 mrg exchange", "fetch and ADD", "fetch and AND", "fetch and OR", and 37 1.1 mrg "fetch and ADD if greater than or equal to zero". 38 1.1 mrg 39 1.1 mrg No barrier or fence semantics are implied by any of the atomic 40 1.1 mrg instructions for manipulating memory; you must specify the barriers 41 1.1 mrg that you wish explicitly, using the provided macros. 42 1.1 mrg 43 1.1 mrg Any integral 32- or 64-bit value can be used as the argument 44 1.1 mrg to these macros, such as "int", "long long", "unsigned long", etc. 45 1.1 mrg The pointers must be aligned to 4 or 8 bytes for 32- or 64-bit data. 46 1.1 mrg The "exchange" and "compare and exchange" macros may also take 47 1.1 mrg pointer values. We use the pseudo-type "VAL" in the documentation 48 1.1 mrg to indicate the use of an appropriate type. */ 49 1.1 mrg #else 50 1.1 mrg /* Atomic instruction macros 51 1.1 mrg 52 1.1 mrg The macros provided by atomic.h simplify access to the Tile 53 1.1 mrg architecture's atomic instructions. Since the architecture 54 1.1 mrg supports test-and-set as its only in-silicon atomic operation, many 55 1.1 mrg of the operations provided by this header are implemented as 56 1.1 mrg fast-path calls to Linux emulation routines. 57 1.1 mrg 58 1.1 mrg Using the kernel for atomic operations allows userspace to take 59 1.1 mrg advantage of the kernel's existing atomic-integer support (managed 60 1.1 mrg by a distributed array of locks). The kernel provides proper 61 1.1 mrg ordering among simultaneous atomic operations on different cores, 62 1.8 mrg and guarantees a process cannot be context-switched part way 63 1.1 mrg through an atomic operation. By virtue of sharing the kernel 64 1.1 mrg atomic implementation, the userspace atomic operations 65 1.1 mrg are compatible with the atomic methods provided by the kernel's 66 1.1 mrg futex() syscall API. Note that these operations never cause Linux 67 1.1 mrg kernel scheduling, and are in fact invisible to the kernel; they 68 1.1 mrg simply act as regular function calls but with an elevated privilege 69 1.1 mrg level. Note that the kernel's distributed lock array is hashed by 70 1.1 mrg using only VA bits from the atomic value's address (to avoid the 71 1.1 mrg performance hit of page table locking and multiple page-table 72 1.1 mrg lookups to get the PA) and only the VA bits that are below page 73 1.1 mrg granularity (to properly lock simultaneous accesses to the same 74 1.1 mrg page mapped at different VAs). As a result, simultaneous atomic 75 1.1 mrg operations on values whose addresses are at the same offset on a 76 1.1 mrg page will contend in the kernel for the same lock array element. 77 1.1 mrg 78 1.1 mrg No barrier or fence semantics are implied by any of the atomic 79 1.1 mrg instructions for manipulating memory; you must specify the barriers 80 1.1 mrg that you wish explicitly, using the provided macros. 81 1.1 mrg 82 1.1 mrg Any integral 32- or 64-bit value can be used as the argument 83 1.1 mrg to these macros, such as "int", "long long", "unsigned long", etc. 84 1.1 mrg The pointers must be aligned to 4 or 8 bytes for 32- or 64-bit data. 85 1.1 mrg The "exchange" and "compare and exchange" macros may also take 86 1.1 mrg pointer values. We use the pseudo-type "VAL" in the documentation 87 1.1 mrg to indicate the use of an appropriate type. 88 1.1 mrg 89 1.1 mrg The 32-bit routines are implemented using a single kernel fast 90 1.1 mrg syscall, as is the 64-bit compare-and-exchange. The other 64-bit 91 1.1 mrg routines are implemented by looping over the 64-bit 92 1.1 mrg compare-and-exchange routine, so may be potentially less efficient. */ 93 1.1 mrg #endif 94 1.1 mrg 95 1.1 mrg #ifdef __tilegx__ 96 1.6 mrg #define SPR_CMPEXCH_VALUE 0x2780 97 1.1 mrg #else 98 1.6 mrg #define __NR_FAST_cmpxchg -1 99 1.6 mrg #define __NR_FAST_atomic_update -2 100 1.6 mrg #define __NR_FAST_cmpxchg64 -3 101 1.1 mrg #endif 102 1.1 mrg 103 1.1 mrg 104 1.1 mrg /* 32-bit integer compare-and-exchange. */ 105 1.1 mrg static __inline __attribute__ ((always_inline)) 106 1.1 mrg int arch_atomic_val_compare_and_exchange_4 (volatile int *mem, 107 1.1 mrg int oldval, int newval) 108 1.1 mrg { 109 1.1 mrg #ifdef __tilegx__ 110 1.1 mrg __insn_mtspr (SPR_CMPEXCH_VALUE, oldval); 111 1.1 mrg return __insn_cmpexch4 (mem, newval); 112 1.1 mrg #else 113 1.1 mrg int result; 114 1.1 mrg __asm__ __volatile__ ("swint1":"=R00" (result), 115 1.1 mrg "=m" (*mem):"R10" (__NR_FAST_cmpxchg), "R00" (mem), 116 1.1 mrg "R01" (oldval), "R02" (newval), "m" (*mem):"r20", 117 1.1 mrg "r21", "r22", "r23", "r24", "r25", "r26", "r27", 118 1.1 mrg "r28", "r29", "memory"); 119 1.1 mrg return result; 120 1.1 mrg #endif 121 1.1 mrg } 122 1.1 mrg 123 1.1 mrg /* 64-bit integer compare-and-exchange. */ 124 1.1 mrg static __inline __attribute__ ((always_inline)) 125 1.1 mrg long long arch_atomic_val_compare_and_exchange_8 (volatile long long 126 1.1 mrg *mem, long long oldval, 127 1.1 mrg long long newval) 128 1.1 mrg { 129 1.1 mrg #ifdef __tilegx__ 130 1.1 mrg __insn_mtspr (SPR_CMPEXCH_VALUE, oldval); 131 1.1 mrg return __insn_cmpexch (mem, newval); 132 1.1 mrg #else 133 1.1 mrg unsigned int result_lo, result_hi; 134 1.1 mrg unsigned int oldval_lo = oldval & 0xffffffffu, oldval_hi = oldval >> 32; 135 1.1 mrg unsigned int newval_lo = newval & 0xffffffffu, newval_hi = newval >> 32; 136 1.1 mrg __asm__ __volatile__ ("swint1":"=R00" (result_lo), "=R01" (result_hi), 137 1.1 mrg "=m" (*mem):"R10" (__NR_FAST_cmpxchg64), "R00" (mem), 138 1.1 mrg "R02" (oldval_lo), "R03" (oldval_hi), 139 1.1 mrg "R04" (newval_lo), "R05" (newval_hi), 140 1.1 mrg "m" (*mem):"r20", "r21", "r22", "r23", "r24", "r25", 141 1.1 mrg "r26", "r27", "r28", "r29", "memory"); 142 1.1 mrg return ((long long) result_hi) << 32 | result_lo; 143 1.1 mrg #endif 144 1.1 mrg } 145 1.1 mrg 146 1.1 mrg /* This non-existent symbol is called for sizes other than "4" and "8", 147 1.1 mrg indicating a bug in the caller. */ 148 1.1 mrg extern int __arch_atomic_error_bad_argument_size (void) 149 1.1 mrg __attribute__ ((warning ("sizeof atomic argument not 4 or 8"))); 150 1.1 mrg 151 1.1 mrg 152 1.1 mrg #define arch_atomic_val_compare_and_exchange(mem, o, n) \ 153 1.1 mrg __extension__ ({ \ 154 1.1 mrg (__typeof(*(mem)))(__typeof(*(mem)-*(mem))) \ 155 1.1 mrg ((sizeof(*(mem)) == 8) ? \ 156 1.1 mrg arch_atomic_val_compare_and_exchange_8( \ 157 1.1 mrg (volatile long long*)(mem), (__typeof((o)-(o)))(o), \ 158 1.1 mrg (__typeof((n)-(n)))(n)) : \ 159 1.1 mrg (sizeof(*(mem)) == 4) ? \ 160 1.1 mrg arch_atomic_val_compare_and_exchange_4( \ 161 1.1 mrg (volatile int*)(mem), (__typeof((o)-(o)))(o), \ 162 1.1 mrg (__typeof((n)-(n)))(n)) : \ 163 1.1 mrg __arch_atomic_error_bad_argument_size()); \ 164 1.1 mrg }) 165 1.1 mrg 166 1.1 mrg #define arch_atomic_bool_compare_and_exchange(mem, o, n) \ 167 1.1 mrg __extension__ ({ \ 168 1.1 mrg __typeof(o) __o = (o); \ 169 1.1 mrg __builtin_expect( \ 170 1.1 mrg __o == arch_atomic_val_compare_and_exchange((mem), __o, (n)), 1); \ 171 1.1 mrg }) 172 1.1 mrg 173 1.1 mrg 174 1.1 mrg /* Loop with compare_and_exchange until we guess the correct value. 175 1.1 mrg Normally "expr" will be an expression using __old and __value. */ 176 1.1 mrg #define __arch_atomic_update_cmpxchg(mem, value, expr) \ 177 1.1 mrg __extension__ ({ \ 178 1.1 mrg __typeof(value) __value = (value); \ 179 1.1 mrg __typeof(*(mem)) *__mem = (mem), __old = *__mem, __guess; \ 180 1.1 mrg do { \ 181 1.1 mrg __guess = __old; \ 182 1.1 mrg __old = arch_atomic_val_compare_and_exchange(__mem, __old, (expr)); \ 183 1.1 mrg } while (__builtin_expect(__old != __guess, 0)); \ 184 1.1 mrg __old; \ 185 1.1 mrg }) 186 1.1 mrg 187 1.1 mrg #ifdef __tilegx__ 188 1.1 mrg 189 1.1 mrg /* Generic atomic op with 8- or 4-byte variant. 190 1.1 mrg The _mask, _addend, and _expr arguments are ignored on tilegx. */ 191 1.1 mrg #define __arch_atomic_update(mem, value, op, _mask, _addend, _expr) \ 192 1.1 mrg __extension__ ({ \ 193 1.1 mrg ((__typeof(*(mem))) \ 194 1.1 mrg ((sizeof(*(mem)) == 8) ? (__typeof(*(mem)-*(mem)))__insn_##op( \ 195 1.1 mrg (volatile void *)(mem), \ 196 1.1 mrg (long long)(__typeof((value)-(value)))(value)) : \ 197 1.1 mrg (sizeof(*(mem)) == 4) ? (int)__insn_##op##4( \ 198 1.1 mrg (volatile void *)(mem), \ 199 1.1 mrg (int)(__typeof((value)-(value)))(value)) : \ 200 1.1 mrg __arch_atomic_error_bad_argument_size())); \ 201 1.1 mrg }) 202 1.1 mrg 203 1.1 mrg #else 204 1.1 mrg 205 1.1 mrg /* This uses TILEPro's fast syscall support to atomically compute: 206 1.1 mrg 207 1.1 mrg int old = *ptr; 208 1.1 mrg *ptr = (old & mask) + addend; 209 1.1 mrg return old; 210 1.1 mrg 211 1.1 mrg This primitive can be used for atomic exchange, add, or, and. 212 1.1 mrg Only 32-bit support is provided. */ 213 1.1 mrg static __inline __attribute__ ((always_inline)) 214 1.1 mrg int 215 1.1 mrg __arch_atomic_update_4 (volatile int *mem, int mask, int addend) 216 1.1 mrg { 217 1.1 mrg int result; 218 1.1 mrg __asm__ __volatile__ ("swint1":"=R00" (result), 219 1.1 mrg "=m" (*mem):"R10" (__NR_FAST_atomic_update), 220 1.1 mrg "R00" (mem), "R01" (mask), "R02" (addend), 221 1.1 mrg "m" (*mem):"r20", "r21", "r22", "r23", "r24", "r25", 222 1.1 mrg "r26", "r27", "r28", "r29", "memory"); 223 1.1 mrg return result; 224 1.1 mrg } 225 1.1 mrg 226 1.1 mrg /* Generic atomic op with 8- or 4-byte variant. 227 1.1 mrg The _op argument is ignored on tilepro. */ 228 1.1 mrg #define __arch_atomic_update(mem, value, _op, mask, addend, expr) \ 229 1.1 mrg __extension__ ({ \ 230 1.1 mrg (__typeof(*(mem)))(__typeof(*(mem)-*(mem))) \ 231 1.1 mrg ((sizeof(*(mem)) == 8) ? \ 232 1.1 mrg __arch_atomic_update_cmpxchg((mem), (value), (expr)) : \ 233 1.1 mrg (sizeof(*(mem)) == 4) ? \ 234 1.1 mrg __arch_atomic_update_4((volatile int*)(mem), \ 235 1.1 mrg (__typeof((mask)-(mask)))(mask), \ 236 1.1 mrg (__typeof((addend)-(addend)))(addend)) : \ 237 1.1 mrg __arch_atomic_error_bad_argument_size()); \ 238 1.1 mrg }) 239 1.1 mrg 240 1.1 mrg #endif /* __tilegx__ */ 241 1.1 mrg 242 1.1 mrg 243 1.1 mrg #define arch_atomic_exchange(mem, newvalue) \ 244 1.1 mrg __arch_atomic_update(mem, newvalue, exch, 0, newvalue, __value) 245 1.1 mrg 246 1.1 mrg #define arch_atomic_add(mem, value) \ 247 1.1 mrg __arch_atomic_update(mem, value, fetchadd, -1, value, __old + __value) 248 1.1 mrg 249 1.1 mrg #define arch_atomic_sub(mem, value) arch_atomic_add((mem), -(value)) 250 1.1 mrg 251 1.1 mrg #define arch_atomic_increment(mem) arch_atomic_add((mem), 1) 252 1.1 mrg 253 1.1 mrg #define arch_atomic_decrement(mem) arch_atomic_add((mem), -1) 254 1.1 mrg 255 1.1 mrg #define arch_atomic_and(mem, mask) \ 256 1.1 mrg __arch_atomic_update(mem, mask, fetchand, mask, 0, __old & __value) 257 1.1 mrg 258 1.1 mrg #define arch_atomic_or(mem, mask) \ 259 1.1 mrg __arch_atomic_update(mem, mask, fetchor, ~mask, mask, __old | __value) 260 1.1 mrg 261 1.1 mrg #define arch_atomic_xor(mem, mask) \ 262 1.1 mrg __arch_atomic_update_cmpxchg(mem, mask, __old ^ __value) 263 1.1 mrg 264 1.1 mrg #define arch_atomic_nand(mem, mask) \ 265 1.1 mrg __arch_atomic_update_cmpxchg(mem, mask, ~(__old & __value)) 266 1.1 mrg 267 1.1 mrg #define arch_atomic_bit_set(mem, bit) \ 268 1.1 mrg __extension__ ({ \ 269 1.1 mrg __typeof(*(mem)) __mask = (__typeof(*(mem)))1 << (bit); \ 270 1.1 mrg __mask & arch_atomic_or((mem), __mask); \ 271 1.1 mrg }) 272 1.1 mrg 273 1.1 mrg #define arch_atomic_bit_clear(mem, bit) \ 274 1.1 mrg __extension__ ({ \ 275 1.1 mrg __typeof(*(mem)) __mask = (__typeof(*(mem)))1 << (bit); \ 276 1.1 mrg __mask & arch_atomic_and((mem), ~__mask); \ 277 1.1 mrg }) 278 1.1 mrg 279 1.1 mrg #ifdef __tilegx__ 280 1.1 mrg /* Atomically store a new value to memory. 281 1.1 mrg Note that you can freely use types of any size here, unlike the 282 1.1 mrg other atomic routines, which require 32- or 64-bit types. 283 1.1 mrg This accessor is provided for compatibility with TILEPro, which 284 1.1 mrg required an explicit atomic operation for stores that needed 285 1.1 mrg to be atomic with respect to other atomic methods in this header. */ 286 1.1 mrg #define arch_atomic_write(mem, value) ((void) (*(mem) = (value))) 287 1.1 mrg #else 288 1.1 mrg #define arch_atomic_write(mem, value) \ 289 1.1 mrg do { \ 290 1.1 mrg __typeof(mem) __aw_mem = (mem); \ 291 1.1 mrg __typeof(value) __aw_val = (value); \ 292 1.1 mrg unsigned int *__aw_mem32, __aw_intval, __aw_val32, __aw_off, __aw_mask; \ 293 1.1 mrg __aw_intval = (__typeof((value) - (value)))__aw_val; \ 294 1.1 mrg switch (sizeof(*__aw_mem)) { \ 295 1.1 mrg case 8: \ 296 1.1 mrg __arch_atomic_update_cmpxchg(__aw_mem, __aw_val, __value); \ 297 1.1 mrg break; \ 298 1.1 mrg case 4: \ 299 1.1 mrg __arch_atomic_update_4((int *)__aw_mem, 0, __aw_intval); \ 300 1.1 mrg break; \ 301 1.1 mrg case 2: \ 302 1.1 mrg __aw_off = 8 * ((long)__aw_mem & 0x2); \ 303 1.1 mrg __aw_mask = 0xffffU << __aw_off; \ 304 1.1 mrg __aw_mem32 = (unsigned int *)((long)__aw_mem & ~0x2); \ 305 1.1 mrg __aw_val32 = (__aw_intval << __aw_off) & __aw_mask; \ 306 1.1 mrg __arch_atomic_update_cmpxchg(__aw_mem32, __aw_val32, \ 307 1.1 mrg (__old & ~__aw_mask) | __value); \ 308 1.1 mrg break; \ 309 1.1 mrg case 1: \ 310 1.1 mrg __aw_off = 8 * ((long)__aw_mem & 0x3); \ 311 1.1 mrg __aw_mask = 0xffU << __aw_off; \ 312 1.1 mrg __aw_mem32 = (unsigned int *)((long)__aw_mem & ~0x3); \ 313 1.1 mrg __aw_val32 = (__aw_intval << __aw_off) & __aw_mask; \ 314 1.1 mrg __arch_atomic_update_cmpxchg(__aw_mem32, __aw_val32, \ 315 1.1 mrg (__old & ~__aw_mask) | __value); \ 316 1.1 mrg break; \ 317 1.1 mrg } \ 318 1.1 mrg } while (0) 319 1.1 mrg #endif 320 1.1 mrg 321 1.1 mrg /* Compiler barrier. 322 1.1 mrg 323 1.1 mrg This macro prevents loads or stores from being moved by the compiler 324 1.1 mrg across the macro. Any loaded value that was loaded before this 325 1.1 mrg macro must then be reloaded by the compiler. */ 326 1.1 mrg #define arch_atomic_compiler_barrier() __asm__ __volatile__("" ::: "memory") 327 1.1 mrg 328 1.1 mrg /* Full memory barrier. 329 1.1 mrg 330 1.1 mrg This macro has the semantics of arch_atomic_compiler_barrer(), but also 331 1.1 mrg ensures that previous stores are visible to other cores, and that 332 1.1 mrg all previous loaded values have been placed into their target 333 1.1 mrg register on this core. */ 334 1.1 mrg #define arch_atomic_full_barrier() __insn_mf() 335 1.1 mrg 336 1.1 mrg /* Read memory barrier. 337 1.1 mrg 338 1.1 mrg Ensure that all reads by this processor that occurred prior to the 339 1.1 mrg read memory barrier have completed, and that no reads that occur 340 1.1 mrg after the read memory barrier on this processor are initiated 341 1.1 mrg before the barrier. 342 1.1 mrg 343 1.1 mrg On current TILE chips a read barrier is implemented as a full barrier, 344 1.1 mrg but this may not be true in later versions of the architecture. 345 1.1 mrg 346 1.1 mrg See also arch_atomic_acquire_barrier() for the appropriate idiom to use 347 1.1 mrg to ensure no reads are lifted above an atomic lock instruction. */ 348 1.1 mrg #define arch_atomic_read_barrier() arch_atomic_full_barrier() 349 1.1 mrg 350 1.1 mrg /* Write memory barrier. 351 1.1 mrg 352 1.1 mrg Ensure that all writes by this processor that occurred prior to the 353 1.1 mrg write memory barrier have completed, and that no writes that occur 354 1.1 mrg after the write memory barrier on this processor are initiated 355 1.1 mrg before the barrier. 356 1.1 mrg 357 1.1 mrg On current TILE chips a write barrier is implemented as a full barrier, 358 1.1 mrg but this may not be true in later versions of the architecture. 359 1.1 mrg 360 1.1 mrg See also arch_atomic_release_barrier() for the appropriate idiom to use 361 1.1 mrg to ensure all writes are complete prior to an atomic unlock instruction. */ 362 1.1 mrg #define arch_atomic_write_barrier() arch_atomic_full_barrier() 363 1.1 mrg 364 1.1 mrg /* Lock acquisition barrier. 365 1.1 mrg 366 1.1 mrg Ensure that no load operations that follow this macro in the 367 1.1 mrg program can issue prior to the barrier. Without such a barrier, 368 1.1 mrg the compiler can reorder them to issue earlier, or the hardware can 369 1.1 mrg issue them speculatively. The latter is not currently done in the 370 1.1 mrg Tile microarchitecture, but using this operation improves 371 1.1 mrg portability to future implementations. 372 1.1 mrg 373 1.1 mrg This operation is intended to be used as part of the "acquire" 374 1.1 mrg path for locking, that is, when entering a critical section. 375 1.1 mrg This should be done after the atomic operation that actually 376 1.1 mrg acquires the lock, and in conjunction with a "control dependency" 377 1.1 mrg that checks the atomic operation result to see if the lock was 378 1.1 mrg in fact acquired. See the arch_atomic_read_barrier() macro 379 1.1 mrg for a heavier-weight barrier to use in certain unusual constructs, 380 1.1 mrg or arch_atomic_acquire_barrier_value() if no control dependency exists. */ 381 1.1 mrg #define arch_atomic_acquire_barrier() arch_atomic_compiler_barrier() 382 1.1 mrg 383 1.1 mrg /* Lock release barrier. 384 1.1 mrg 385 1.1 mrg Ensure that no store operations that precede this macro in the 386 1.1 mrg program complete subsequent to the barrier. Without such a 387 1.1 mrg barrier, the compiler can reorder stores to issue later, or stores 388 1.1 mrg can be still outstanding in the memory network. 389 1.1 mrg 390 1.1 mrg This operation is intended to be used as part of the "release" path 391 1.1 mrg for locking, that is, when leaving a critical section. This should 392 1.1 mrg be done before the operation (such as a store of zero) that 393 1.1 mrg actually releases the lock. */ 394 1.1 mrg #define arch_atomic_release_barrier() arch_atomic_write_barrier() 395 1.1 mrg 396 1.1 mrg /* Barrier until the read of a particular value is complete. 397 1.1 mrg 398 1.1 mrg This is occasionally useful when constructing certain locking 399 1.1 mrg scenarios. For example, you might write a routine that issues an 400 1.1 mrg atomic instruction to enter a critical section, then reads one or 401 1.1 mrg more values within the critical section without checking to see if 402 1.1 mrg the critical section was in fact acquired, and only later checks 403 1.1 mrg the atomic instruction result to see if the lock was acquired. If 404 1.1 mrg so the routine could properly release the lock and know that the 405 1.1 mrg values that were read were valid. 406 1.1 mrg 407 1.1 mrg In this scenario, it is required to wait for the result of the 408 1.1 mrg atomic instruction, even if the value itself is not checked. This 409 1.1 mrg guarantees that if the atomic instruction succeeded in taking the lock, 410 1.1 mrg the lock was held before any reads in the critical section issued. */ 411 1.1 mrg #define arch_atomic_acquire_barrier_value(val) \ 412 1.1 mrg __asm__ __volatile__("move %0, %0" :: "r"(val)) 413 1.1 mrg 414 1.1 mrg /* Access the given variable in memory exactly once. 415 1.1 mrg 416 1.1 mrg In some contexts, an algorithm may need to force access to memory, 417 1.1 mrg since otherwise the compiler may think it can optimize away a 418 1.1 mrg memory load or store; for example, in a loop when polling memory to 419 1.1 mrg see if another cpu has updated it yet. Generally this is only 420 1.1 mrg required for certain very carefully hand-tuned algorithms; using it 421 1.1 mrg unnecessarily may result in performance losses. 422 1.1 mrg 423 1.1 mrg A related use of this macro is to ensure that the compiler does not 424 1.1 mrg rematerialize the value of "x" by reloading it from memory 425 1.1 mrg unexpectedly; the "volatile" marking will prevent the compiler from 426 1.1 mrg being able to rematerialize. This is helpful if an algorithm needs 427 1.1 mrg to read a variable without locking, but needs it to have the same 428 1.1 mrg value if it ends up being used several times within the algorithm. 429 1.1 mrg 430 1.1 mrg Note that multiple uses of this macro are guaranteed to be ordered, 431 1.1 mrg i.e. the compiler will not reorder stores or loads that are wrapped 432 1.1 mrg in arch_atomic_access_once(). */ 433 1.1 mrg #define arch_atomic_access_once(x) (*(volatile __typeof(x) *)&(x)) 434 1.1 mrg 435 1.1 mrg 436 1.1 mrg 437 1.1 mrg #endif /* !_ATOMIC_H_ */ 438