1*17c59111Sjsg /* $OpenBSD: atomic.h,v 1.24 2025/01/19 11:15:52 jsg Exp $ */ 27f4dd379Sjsg /** 37f4dd379Sjsg * \file drm_atomic.h 47f4dd379Sjsg * Atomic operations used in the DRM which may or may not be provided by the OS. 57f4dd379Sjsg * 67f4dd379Sjsg * \author Eric Anholt <anholt@FreeBSD.org> 77f4dd379Sjsg */ 87f4dd379Sjsg 97f4dd379Sjsg /*- 107f4dd379Sjsg * Copyright 2004 Eric Anholt 117f4dd379Sjsg * All Rights Reserved. 127f4dd379Sjsg * 137f4dd379Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 147f4dd379Sjsg * copy of this software and associated documentation files (the "Software"), 157f4dd379Sjsg * to deal in the Software without restriction, including without limitation 167f4dd379Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 177f4dd379Sjsg * and/or sell copies of the Software, and to permit persons to whom the 187f4dd379Sjsg * Software is furnished to do so, subject to the following conditions: 197f4dd379Sjsg * 207f4dd379Sjsg * The above copyright notice and this permission notice (including the next 217f4dd379Sjsg * paragraph) shall be included in all copies or substantial portions of the 227f4dd379Sjsg * Software. 237f4dd379Sjsg * 247f4dd379Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 257f4dd379Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 267f4dd379Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 277f4dd379Sjsg * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 287f4dd379Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 297f4dd379Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 307f4dd379Sjsg * OTHER DEALINGS IN THE SOFTWARE. 317f4dd379Sjsg */ 327f4dd379Sjsg 337f4dd379Sjsg #ifndef _DRM_LINUX_ATOMIC_H_ 347f4dd379Sjsg #define _DRM_LINUX_ATOMIC_H_ 357f4dd379Sjsg 367f4dd379Sjsg #include <sys/types.h> 377f4dd379Sjsg #include <sys/mutex.h> 387f4dd379Sjsg #include <machine/intr.h> 397f4dd379Sjsg #include <linux/types.h> 40c349dbc7Sjsg #include <linux/compiler.h> /* via x86/include/asm/atomic.h */ 41c349dbc7Sjsg 42c349dbc7Sjsg #define ATOMIC_INIT(x) (x) 437f4dd379Sjsg 44b40fc73fSjsg #define atomic_set(p, v) WRITE_ONCE(*(p), (v)) 45b40fc73fSjsg #define atomic_read(p) READ_ONCE(*(p)) 467f4dd379Sjsg #define atomic_inc(p) __sync_fetch_and_add(p, 1) 477f4dd379Sjsg #define atomic_dec(p) __sync_fetch_and_sub(p, 1) 487f4dd379Sjsg #define atomic_add(n, p) __sync_fetch_and_add(p, n) 497f4dd379Sjsg #define atomic_sub(n, p) __sync_fetch_and_sub(p, n) 50c349dbc7Sjsg #define atomic_and(n, p) __sync_fetch_and_and(p, n) 51c349dbc7Sjsg #define atomic_or(n, p) atomic_setbits_int(p, n) 527f4dd379Sjsg #define atomic_add_return(n, p) __sync_add_and_fetch(p, n) 537f4dd379Sjsg #define atomic_sub_return(n, p) __sync_sub_and_fetch(p, n) 545ca02815Sjsg #define atomic_sub_and_test(n, p) (atomic_sub_return(n, p) == 0) 557f4dd379Sjsg #define atomic_inc_return(v) atomic_add_return(1, (v)) 567f4dd379Sjsg #define atomic_dec_return(v) atomic_sub_return(1, (v)) 577f4dd379Sjsg #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) 587f4dd379Sjsg #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) 597f4dd379Sjsg #define atomic_cmpxchg(p, o, n) __sync_val_compare_and_swap(p, o, n) 60237c592dSjsg #define cmpxchg(p, o, n) __sync_val_compare_and_swap(p, o, n) 615ca02815Sjsg #define cmpxchg64(p, o, n) __sync_val_compare_and_swap(p, o, n) 627f4dd379Sjsg #define atomic_set_release(p, v) atomic_set((p), (v)) 6324a9071dSjsg #define atomic_andnot(bits, p) atomic_clearbits_int(p,bits) 6424a9071dSjsg #define atomic_fetch_inc(p) __sync_fetch_and_add(p, 1) 6524a9071dSjsg #define atomic_fetch_xor(n, p) __sync_fetch_and_xor(p, n) 667f4dd379Sjsg 67c349dbc7Sjsg #define try_cmpxchg(p, op, n) \ 68c349dbc7Sjsg ({ \ 69c349dbc7Sjsg __typeof(p) __op = (__typeof((p)))(op); \ 70c349dbc7Sjsg __typeof(*(p)) __o = *__op; \ 71c349dbc7Sjsg __typeof(*(p)) __p = __sync_val_compare_and_swap((p), (__o), (n)); \ 72c349dbc7Sjsg if (__p != __o) \ 73c349dbc7Sjsg *__op = __p; \ 74c349dbc7Sjsg (__p == __o); \ 75c349dbc7Sjsg }) 76c349dbc7Sjsg 77c349dbc7Sjsg static inline bool 78c349dbc7Sjsg atomic_try_cmpxchg(volatile int *p, int *op, int n) 79c349dbc7Sjsg { 80c349dbc7Sjsg return try_cmpxchg(p, op, n); 81c349dbc7Sjsg } 82c349dbc7Sjsg 837f4dd379Sjsg static inline int 847f4dd379Sjsg atomic_xchg(volatile int *v, int n) 857f4dd379Sjsg { 867f4dd379Sjsg __sync_synchronize(); 877f4dd379Sjsg return __sync_lock_test_and_set(v, n); 887f4dd379Sjsg } 897f4dd379Sjsg 907f4dd379Sjsg #define xchg(v, n) __sync_lock_test_and_set(v, n) 917f4dd379Sjsg 927f4dd379Sjsg static inline int 937f4dd379Sjsg atomic_add_unless(volatile int *v, int n, int u) 947f4dd379Sjsg { 95de9d0d99Sjsg int o; 967f4dd379Sjsg 977f4dd379Sjsg do { 987f4dd379Sjsg o = *v; 997f4dd379Sjsg if (o == u) 1007f4dd379Sjsg return 0; 1017f4dd379Sjsg } while (__sync_val_compare_and_swap(v, o, o +n) != o); 1027f4dd379Sjsg 1037f4dd379Sjsg return 1; 1047f4dd379Sjsg } 1057f4dd379Sjsg 1065cf16f9fSjsg #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 1075cf16f9fSjsg 1087f4dd379Sjsg static inline int 1097f4dd379Sjsg atomic_dec_if_positive(volatile int *v) 1107f4dd379Sjsg { 1117f4dd379Sjsg int r, o; 1127f4dd379Sjsg 1137f4dd379Sjsg do { 1147f4dd379Sjsg o = *v; 1157f4dd379Sjsg r = o - 1; 1167f4dd379Sjsg if (r < 0) 1177f4dd379Sjsg break; 1187f4dd379Sjsg } while (__sync_val_compare_and_swap(v, o, r) != o); 1197f4dd379Sjsg 1207f4dd379Sjsg return r; 1217f4dd379Sjsg } 1227f4dd379Sjsg 123b40fc73fSjsg #define atomic_long_read(p) READ_ONCE(*(p)) 1247f4dd379Sjsg 12505e32666Sjsg /* 32 bit powerpc lacks 64 bit atomics */ 12605e32666Sjsg #if !defined(__powerpc__) || defined(__powerpc64__) 12705e32666Sjsg 128*17c59111Sjsg typedef int64_t atomic64_t __aligned(8); 1297f4dd379Sjsg 130c349dbc7Sjsg #define ATOMIC64_INIT(x) (x) 131c349dbc7Sjsg 132b40fc73fSjsg #define atomic64_set(p, v) WRITE_ONCE(*(p), (v)) 133b40fc73fSjsg #define atomic64_read(p) READ_ONCE(*(p)) 1347f4dd379Sjsg 1357f4dd379Sjsg static inline int64_t 136*17c59111Sjsg atomic64_xchg(atomic64_t *v, int64_t n) 1377f4dd379Sjsg { 1387f4dd379Sjsg __sync_synchronize(); 1397f4dd379Sjsg return __sync_lock_test_and_set(v, n); 1407f4dd379Sjsg } 1417f4dd379Sjsg 14236ce76eeSkettenis static inline int64_t 143*17c59111Sjsg atomic64_cmpxchg(atomic64_t *v, int64_t o, int64_t n) 14436ce76eeSkettenis { 14536ce76eeSkettenis return __sync_val_compare_and_swap(v, o, n); 14636ce76eeSkettenis } 14736ce76eeSkettenis 1487f4dd379Sjsg #define atomic64_add(n, p) __sync_fetch_and_add_8(p, n) 1497f4dd379Sjsg #define atomic64_sub(n, p) __sync_fetch_and_sub_8(p, n) 1507f4dd379Sjsg #define atomic64_inc(p) __sync_fetch_and_add_8(p, 1) 1517f4dd379Sjsg #define atomic64_add_return(n, p) __sync_add_and_fetch_8(p, n) 1527f4dd379Sjsg #define atomic64_inc_return(p) __sync_add_and_fetch_8(p, 1) 1537f4dd379Sjsg 1547f4dd379Sjsg #else 1557f4dd379Sjsg 156ec70c0c7Sjsg extern struct mutex atomic64_mtx; 157ec70c0c7Sjsg 1587f4dd379Sjsg typedef struct { 1597f4dd379Sjsg volatile int64_t val; 1607f4dd379Sjsg } atomic64_t; 1617f4dd379Sjsg 162ec70c0c7Sjsg #define ATOMIC64_INIT(x) { (x) } 163c349dbc7Sjsg 1647f4dd379Sjsg static inline void 1657f4dd379Sjsg atomic64_set(atomic64_t *v, int64_t i) 1667f4dd379Sjsg { 167ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 1687f4dd379Sjsg v->val = i; 169ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 1707f4dd379Sjsg } 1717f4dd379Sjsg 1727f4dd379Sjsg static inline int64_t 1737f4dd379Sjsg atomic64_read(atomic64_t *v) 1747f4dd379Sjsg { 1757f4dd379Sjsg int64_t val; 1767f4dd379Sjsg 177ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 1787f4dd379Sjsg val = v->val; 179ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 1807f4dd379Sjsg 1817f4dd379Sjsg return val; 1827f4dd379Sjsg } 1837f4dd379Sjsg 1847f4dd379Sjsg static inline int64_t 1857f4dd379Sjsg atomic64_xchg(atomic64_t *v, int64_t n) 1867f4dd379Sjsg { 1877f4dd379Sjsg int64_t val; 1887f4dd379Sjsg 189ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 1907f4dd379Sjsg val = v->val; 1917f4dd379Sjsg v->val = n; 192ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 1937f4dd379Sjsg 1947f4dd379Sjsg return val; 1957f4dd379Sjsg } 1967f4dd379Sjsg 1977f4dd379Sjsg static inline void 1987f4dd379Sjsg atomic64_add(int i, atomic64_t *v) 1997f4dd379Sjsg { 200ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 2017f4dd379Sjsg v->val += i; 202ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 2037f4dd379Sjsg } 2047f4dd379Sjsg 2057f4dd379Sjsg #define atomic64_inc(p) atomic64_add(p, 1) 2067f4dd379Sjsg 2077f4dd379Sjsg static inline int64_t 2087f4dd379Sjsg atomic64_add_return(int i, atomic64_t *v) 2097f4dd379Sjsg { 2107f4dd379Sjsg int64_t val; 2117f4dd379Sjsg 212ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 2137f4dd379Sjsg val = v->val + i; 2147f4dd379Sjsg v->val = val; 215ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 2167f4dd379Sjsg 2177f4dd379Sjsg return val; 2187f4dd379Sjsg } 2197f4dd379Sjsg 220f005ef32Sjsg #define atomic64_inc_return(p) atomic64_add_return(1, p) 2217f4dd379Sjsg 2227f4dd379Sjsg static inline void 2237f4dd379Sjsg atomic64_sub(int i, atomic64_t *v) 2247f4dd379Sjsg { 225ec70c0c7Sjsg mtx_enter(&atomic64_mtx); 2267f4dd379Sjsg v->val -= i; 227ec70c0c7Sjsg mtx_leave(&atomic64_mtx); 2287f4dd379Sjsg } 2297f4dd379Sjsg #endif 2307f4dd379Sjsg 2317f4dd379Sjsg #ifdef __LP64__ 2327f4dd379Sjsg typedef int64_t atomic_long_t; 2337f4dd379Sjsg #define atomic_long_set(p, v) atomic64_set(p, v) 2347f4dd379Sjsg #define atomic_long_xchg(v, n) atomic64_xchg(v, n) 2357f4dd379Sjsg #define atomic_long_cmpxchg(p, o, n) atomic_cmpxchg(p, o, n) 2365ca02815Sjsg #define atomic_long_add(i, v) atomic64_add(i, v) 2375ca02815Sjsg #define atomic_long_sub(i, v) atomic64_sub(i, v) 2387f4dd379Sjsg #else 2397f4dd379Sjsg typedef int32_t atomic_long_t; 2407f4dd379Sjsg #define atomic_long_set(p, v) atomic_set(p, v) 2417f4dd379Sjsg #define atomic_long_xchg(v, n) atomic_xchg(v, n) 2427f4dd379Sjsg #define atomic_long_cmpxchg(p, o, n) atomic_cmpxchg(p, o, n) 2435ca02815Sjsg #define atomic_long_add(i, v) atomic_add(i, v) 2445ca02815Sjsg #define atomic_long_sub(i, v) atomic_sub(i, v) 2457f4dd379Sjsg #endif 2467f4dd379Sjsg 2477f4dd379Sjsg static inline atomic_t 2487f4dd379Sjsg test_and_set_bit(u_int b, volatile void *p) 2497f4dd379Sjsg { 2507f4dd379Sjsg unsigned int m = 1 << (b & 0x1f); 2517f4dd379Sjsg unsigned int prev = __sync_fetch_and_or((volatile u_int *)p + (b >> 5), m); 2527f4dd379Sjsg return (prev & m) != 0; 2537f4dd379Sjsg } 2547f4dd379Sjsg 2557f4dd379Sjsg static inline void 2567f4dd379Sjsg clear_bit(u_int b, volatile void *p) 2577f4dd379Sjsg { 25824a9071dSjsg atomic_clearbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f)); 2597f4dd379Sjsg } 2607f4dd379Sjsg 2617f4dd379Sjsg static inline void 262c349dbc7Sjsg clear_bit_unlock(u_int b, volatile void *p) 263c349dbc7Sjsg { 264c349dbc7Sjsg membar_enter(); 265c349dbc7Sjsg clear_bit(b, p); 266c349dbc7Sjsg } 267c349dbc7Sjsg 268c349dbc7Sjsg static inline void 2697f4dd379Sjsg set_bit(u_int b, volatile void *p) 2707f4dd379Sjsg { 27124a9071dSjsg atomic_setbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f)); 2727f4dd379Sjsg } 2737f4dd379Sjsg 2747f4dd379Sjsg static inline void 2757f4dd379Sjsg __clear_bit(u_int b, volatile void *p) 2767f4dd379Sjsg { 2777f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 2787f4dd379Sjsg ptr[b >> 5] &= ~(1 << (b & 0x1f)); 2797f4dd379Sjsg } 2807f4dd379Sjsg 2817f4dd379Sjsg static inline void 2827f4dd379Sjsg __set_bit(u_int b, volatile void *p) 2837f4dd379Sjsg { 2847f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 2857f4dd379Sjsg ptr[b >> 5] |= (1 << (b & 0x1f)); 2867f4dd379Sjsg } 2877f4dd379Sjsg 2887f4dd379Sjsg static inline int 2897f4dd379Sjsg test_bit(u_int b, const volatile void *p) 2907f4dd379Sjsg { 2917f4dd379Sjsg return !!(((volatile u_int *)p)[b >> 5] & (1 << (b & 0x1f))); 2927f4dd379Sjsg } 2937f4dd379Sjsg 2947f4dd379Sjsg static inline int 2957f4dd379Sjsg __test_and_set_bit(u_int b, volatile void *p) 2967f4dd379Sjsg { 2977f4dd379Sjsg unsigned int m = 1 << (b & 0x1f); 2987f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 2997f4dd379Sjsg unsigned int prev = ptr[b >> 5]; 3007f4dd379Sjsg ptr[b >> 5] |= m; 3017f4dd379Sjsg 3027f4dd379Sjsg return (prev & m) != 0; 3037f4dd379Sjsg } 3047f4dd379Sjsg 3057f4dd379Sjsg static inline int 3067f4dd379Sjsg test_and_clear_bit(u_int b, volatile void *p) 3077f4dd379Sjsg { 3087f4dd379Sjsg unsigned int m = 1 << (b & 0x1f); 3097f4dd379Sjsg unsigned int prev = __sync_fetch_and_and((volatile u_int *)p + (b >> 5), ~m); 3107f4dd379Sjsg return (prev & m) != 0; 3117f4dd379Sjsg } 3127f4dd379Sjsg 3137f4dd379Sjsg static inline int 3147f4dd379Sjsg __test_and_clear_bit(u_int b, volatile void *p) 3157f4dd379Sjsg { 3167f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 3177f4dd379Sjsg int rv = !!(ptr[b >> 5] & (1 << (b & 0x1f))); 3187f4dd379Sjsg ptr[b >> 5] &= ~(1 << (b & 0x1f)); 3197f4dd379Sjsg return rv; 3207f4dd379Sjsg } 3217f4dd379Sjsg 3227f4dd379Sjsg static inline int 3237f4dd379Sjsg find_first_zero_bit(volatile void *p, int max) 3247f4dd379Sjsg { 3257f4dd379Sjsg int b; 3267f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 3277f4dd379Sjsg 3287f4dd379Sjsg for (b = 0; b < max; b += 32) { 3297f4dd379Sjsg if (ptr[b >> 5] != ~0) { 3307f4dd379Sjsg for (;;) { 3317f4dd379Sjsg if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) 3327f4dd379Sjsg return b; 3337f4dd379Sjsg b++; 3347f4dd379Sjsg } 3357f4dd379Sjsg } 3367f4dd379Sjsg } 3377f4dd379Sjsg return max; 3387f4dd379Sjsg } 3397f4dd379Sjsg 3407f4dd379Sjsg static inline int 3417f4dd379Sjsg find_next_zero_bit(volatile void *p, int max, int b) 3427f4dd379Sjsg { 3437f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 3447f4dd379Sjsg 3457f4dd379Sjsg for (; b < max; b += 32) { 3467f4dd379Sjsg if (ptr[b >> 5] != ~0) { 3477f4dd379Sjsg for (;;) { 3487f4dd379Sjsg if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) 3497f4dd379Sjsg return b; 3507f4dd379Sjsg b++; 3517f4dd379Sjsg } 3527f4dd379Sjsg } 3537f4dd379Sjsg } 3547f4dd379Sjsg return max; 3557f4dd379Sjsg } 3567f4dd379Sjsg 3577f4dd379Sjsg static inline int 3587f4dd379Sjsg find_first_bit(volatile void *p, int max) 3597f4dd379Sjsg { 3607f4dd379Sjsg int b; 3617f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 3627f4dd379Sjsg 3637f4dd379Sjsg for (b = 0; b < max; b += 32) { 3647f4dd379Sjsg if (ptr[b >> 5] != 0) { 3657f4dd379Sjsg for (;;) { 3667f4dd379Sjsg if (ptr[b >> 5] & (1 << (b & 0x1f))) 3677f4dd379Sjsg return b; 3687f4dd379Sjsg b++; 3697f4dd379Sjsg } 3707f4dd379Sjsg } 3717f4dd379Sjsg } 3727f4dd379Sjsg return max; 3737f4dd379Sjsg } 3747f4dd379Sjsg 3757f4dd379Sjsg static inline int 3761bb76ff1Sjsg find_next_bit(const volatile void *p, int max, int b) 3777f4dd379Sjsg { 3787f4dd379Sjsg volatile u_int *ptr = (volatile u_int *)p; 3797f4dd379Sjsg 3807f4dd379Sjsg for (; b < max; b+= 32) { 3817f4dd379Sjsg if (ptr[b >> 5] != 0) { 3827f4dd379Sjsg for (;;) { 3837f4dd379Sjsg if (ptr[b >> 5] & (1 << (b & 0x1f))) 3847f4dd379Sjsg return b; 3857f4dd379Sjsg b++; 3867f4dd379Sjsg } 3877f4dd379Sjsg } 3887f4dd379Sjsg } 3897f4dd379Sjsg return max; 3907f4dd379Sjsg } 3917f4dd379Sjsg 3927f4dd379Sjsg #define for_each_set_bit(b, p, max) \ 3937f4dd379Sjsg for ((b) = find_first_bit((p), (max)); \ 3947f4dd379Sjsg (b) < (max); \ 3957f4dd379Sjsg (b) = find_next_bit((p), (max), (b) + 1)) 3967f4dd379Sjsg 3977f4dd379Sjsg #define for_each_clear_bit(b, p, max) \ 3987f4dd379Sjsg for ((b) = find_first_zero_bit((p), (max)); \ 3997f4dd379Sjsg (b) < (max); \ 4007f4dd379Sjsg (b) = find_next_zero_bit((p), (max), (b) + 1)) 4017f4dd379Sjsg 4027f4dd379Sjsg #if defined(__i386__) 403733a71f2Sjsg #define rmb() __asm volatile("lock; addl $0,-4(%%esp)" : : : "memory", "cc") 404733a71f2Sjsg #define wmb() __asm volatile("lock; addl $0,-4(%%esp)" : : : "memory", "cc") 405733a71f2Sjsg #define mb() __asm volatile("lock; addl $0,-4(%%esp)" : : : "memory", "cc") 406733a71f2Sjsg #define smp_mb() __asm volatile("lock; addl $0,-4(%%esp)" : : : "memory", "cc") 4072915e44aSjsg #define smp_rmb() __membar("") 4082915e44aSjsg #define smp_wmb() __membar("") 4092d50d9caSjsg #define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0) 4102d50d9caSjsg #define smp_mb__after_atomic() do { } while (0) 4112d50d9caSjsg #define smp_mb__before_atomic() do { } while (0) 4127f4dd379Sjsg #elif defined(__amd64__) 4132915e44aSjsg #define rmb() __membar("lfence") 4142915e44aSjsg #define wmb() __membar("sfence") 4152915e44aSjsg #define mb() __membar("mfence") 416733a71f2Sjsg #define smp_mb() __asm volatile("lock; addl $0,-4(%%rsp)" : : : "memory", "cc") 4172915e44aSjsg #define smp_rmb() __membar("") 4182915e44aSjsg #define smp_wmb() __membar("") 4192d50d9caSjsg #define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0) 4202d50d9caSjsg #define smp_mb__after_atomic() do { } while (0) 4212d50d9caSjsg #define smp_mb__before_atomic() do { } while (0) 4227f4dd379Sjsg #elif defined(__aarch64__) 423a2e16862Sjsg #define rmb() __membar("dsb ld") 424a2e16862Sjsg #define wmb() __membar("dsb st") 425a2e16862Sjsg #define mb() __membar("dsb sy") 426667382c7Skettenis #define dma_rmb() __membar("dmb oshld") 427667382c7Skettenis #define dma_wmb() __membar("dmb oshst") 4287b0a2893Sjsg #define dma_mb() __membar("dmb osh") 429f005ef32Sjsg #define smp_mb() __membar("dmb ish") 4305ca02815Sjsg #elif defined(__arm__) 4315ca02815Sjsg #define rmb() __membar("dsb sy") 4325ca02815Sjsg #define wmb() __membar("dsb sy") 4335ca02815Sjsg #define mb() __membar("dsb sy") 4347f4dd379Sjsg #elif defined(__mips64__) 435a2e16862Sjsg #define rmb() mips_sync() 436a2e16862Sjsg #define wmb() mips_sync() 437a2e16862Sjsg #define mb() mips_sync() 438ff53255bSjsg #elif defined(__powerpc64__) 439ff53255bSjsg #define rmb() __membar("sync") 440ff53255bSjsg #define wmb() __membar("sync") 441ff53255bSjsg #define mb() __membar("sync") 442ff53255bSjsg #define smp_rmb() __membar("lwsync") 443ff53255bSjsg #define smp_wmb() __membar("lwsync") 444f005ef32Sjsg #define smp_mb() __membar("sync") 4457f4dd379Sjsg #elif defined(__powerpc__) 446ff53255bSjsg #define rmb() __membar("sync") 447ff53255bSjsg #define wmb() __membar("sync") 448ff53255bSjsg #define mb() __membar("sync") 449ff53255bSjsg #define smp_wmb() __membar("eieio") 450fee0b6a1Sjsg #elif defined(__riscv) 451fee0b6a1Sjsg #define rmb() __membar("fence ir,ir") 452fee0b6a1Sjsg #define wmb() __membar("fence ow,ow") 453fee0b6a1Sjsg #define mb() __membar("fence iorw,iorw") 454fee0b6a1Sjsg #define smp_rmb() __membar("fence r,r") 455fee0b6a1Sjsg #define smp_wmb() __membar("fence w,w") 456fee0b6a1Sjsg #define smp_mb() __membar("fence rw,rw") 4577f4dd379Sjsg #elif defined(__sparc64__) 458a2e16862Sjsg #define rmb() membar_sync() 459a2e16862Sjsg #define wmb() membar_sync() 460a2e16862Sjsg #define mb() membar_sync() 4617f4dd379Sjsg #endif 4627f4dd379Sjsg 463a2e16862Sjsg #ifndef smp_rmb 464a2e16862Sjsg #define smp_rmb() rmb() 465a2e16862Sjsg #endif 4667f4dd379Sjsg 467a2e16862Sjsg #ifndef smp_wmb 468a2e16862Sjsg #define smp_wmb() wmb() 469a2e16862Sjsg #endif 4707f4dd379Sjsg 471a2e16862Sjsg #ifndef mmiowb 472a2e16862Sjsg #define mmiowb() wmb() 473a2e16862Sjsg #endif 474a2e16862Sjsg 475a2e16862Sjsg #ifndef smp_mb__before_atomic 476a2e16862Sjsg #define smp_mb__before_atomic() mb() 477a2e16862Sjsg #endif 478a2e16862Sjsg 479a2e16862Sjsg #ifndef smp_mb__after_atomic 480a2e16862Sjsg #define smp_mb__after_atomic() mb() 481a2e16862Sjsg #endif 482a2e16862Sjsg 483a2e16862Sjsg #ifndef smp_store_mb 484a2e16862Sjsg #define smp_store_mb(x, v) do { x = v; mb(); } while (0) 485a2e16862Sjsg #endif 4867f4dd379Sjsg 487f005ef32Sjsg #ifndef smp_store_release 488f005ef32Sjsg #define smp_store_release(x, v) do { smp_mb(); WRITE_ONCE(*x, v); } while(0) 489f005ef32Sjsg #endif 490f005ef32Sjsg 491f005ef32Sjsg #ifndef smp_load_acquire 492f005ef32Sjsg #define smp_load_acquire(x) \ 493f005ef32Sjsg ({ \ 494f005ef32Sjsg __typeof(*x) _v = READ_ONCE(*x); \ 495f005ef32Sjsg smp_mb(); \ 496f005ef32Sjsg _v; \ 497f005ef32Sjsg }) 498f005ef32Sjsg #endif 499f005ef32Sjsg 5007f4dd379Sjsg #endif 501