xref: /openbsd-src/sys/dev/pci/drm/include/linux/atomic.h (revision 17c59111eb91c69c5ac2ab69df0c207ff4119e30)
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