forked from mirrors/linux
		
	 67d1b0de25
			
		
	
	
		67d1b0de25
		
	
	
	
	
		
			
			Now that all architectures provide arch_{atomic,atomic64}_*(), we can
build arch_atomic_long_*() atop these, which can be safely used in
noinstr code. The regular atomic_long_*() wrappers are built atop these,
as we do for {atomic,atomic64}_*() atop arch_{atomic,atomic64}_*().
We don't provide arch_* versions of the cond_read*() variants, as we
don't have arch_* versions of the underlying atomic/atomic64 functions
(nor the smp_cond_load*() helpers these are typically based on).
Note that the headers in this patch under include/linux/atomic/ are
generated by the scripts in scripts/atomic/.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210713105253.7615-5-mark.rutland@arm.com
		
	
			
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0 */
 | |
| /* Atomic operations usable in machine independent code */
 | |
| #ifndef _LINUX_ATOMIC_H
 | |
| #define _LINUX_ATOMIC_H
 | |
| #include <linux/types.h>
 | |
| 
 | |
| #include <asm/atomic.h>
 | |
| #include <asm/barrier.h>
 | |
| 
 | |
| /*
 | |
|  * Relaxed variants of xchg, cmpxchg and some atomic operations.
 | |
|  *
 | |
|  * We support four variants:
 | |
|  *
 | |
|  * - Fully ordered: The default implementation, no suffix required.
 | |
|  * - Acquire: Provides ACQUIRE semantics, _acquire suffix.
 | |
|  * - Release: Provides RELEASE semantics, _release suffix.
 | |
|  * - Relaxed: No ordering guarantees, _relaxed suffix.
 | |
|  *
 | |
|  * For compound atomics performing both a load and a store, ACQUIRE
 | |
|  * semantics apply only to the load and RELEASE semantics only to the
 | |
|  * store portion of the operation. Note that a failed cmpxchg_acquire
 | |
|  * does -not- imply any memory ordering constraints.
 | |
|  *
 | |
|  * See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions.
 | |
|  */
 | |
| 
 | |
| #define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
 | |
| #define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
 | |
| 
 | |
| #define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
 | |
| #define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
 | |
| 
 | |
| /*
 | |
|  * The idea here is to build acquire/release variants by adding explicit
 | |
|  * barriers on top of the relaxed variant. In the case where the relaxed
 | |
|  * variant is already fully ordered, no additional barriers are needed.
 | |
|  *
 | |
|  * If an architecture overrides __atomic_acquire_fence() it will probably
 | |
|  * want to define smp_mb__after_spinlock().
 | |
|  */
 | |
| #ifndef __atomic_acquire_fence
 | |
| #define __atomic_acquire_fence		smp_mb__after_atomic
 | |
| #endif
 | |
| 
 | |
| #ifndef __atomic_release_fence
 | |
| #define __atomic_release_fence		smp_mb__before_atomic
 | |
| #endif
 | |
| 
 | |
| #ifndef __atomic_pre_full_fence
 | |
| #define __atomic_pre_full_fence		smp_mb__before_atomic
 | |
| #endif
 | |
| 
 | |
| #ifndef __atomic_post_full_fence
 | |
| #define __atomic_post_full_fence	smp_mb__after_atomic
 | |
| #endif
 | |
| 
 | |
| #define __atomic_op_acquire(op, args...)				\
 | |
| ({									\
 | |
| 	typeof(op##_relaxed(args)) __ret  = op##_relaxed(args);		\
 | |
| 	__atomic_acquire_fence();					\
 | |
| 	__ret;								\
 | |
| })
 | |
| 
 | |
| #define __atomic_op_release(op, args...)				\
 | |
| ({									\
 | |
| 	__atomic_release_fence();					\
 | |
| 	op##_relaxed(args);						\
 | |
| })
 | |
| 
 | |
| #define __atomic_op_fence(op, args...)					\
 | |
| ({									\
 | |
| 	typeof(op##_relaxed(args)) __ret;				\
 | |
| 	__atomic_pre_full_fence();					\
 | |
| 	__ret = op##_relaxed(args);					\
 | |
| 	__atomic_post_full_fence();					\
 | |
| 	__ret;								\
 | |
| })
 | |
| 
 | |
| #include <linux/atomic/atomic-arch-fallback.h>
 | |
| #include <linux/atomic/atomic-long.h>
 | |
| #include <linux/atomic/atomic-instrumented.h>
 | |
| 
 | |
| #endif /* _LINUX_ATOMIC_H */
 |