arch/powerpc/include/asm/atomic.h

Source file repositories/reference/linux-study-clean/arch/powerpc/include/asm/atomic.h

File Facts

System
Linux kernel
Corpus path
arch/powerpc/include/asm/atomic.h
Extension
.h
Size
11827 bytes
Lines
454
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef _ASM_POWERPC_ATOMIC_H_
#define _ASM_POWERPC_ATOMIC_H_

/*
 * PowerPC atomic operations
 */

#ifdef __KERNEL__
#include <linux/types.h>
#include <asm/cmpxchg.h>
#include <asm/barrier.h>
#include <asm/asm-const.h>
#include <asm/asm-compat.h>

/*
 * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with
 * a "bne-" instruction at the end, so an isync is enough as a acquire barrier
 * on the platform without lwsync.
 */
#define __atomic_acquire_fence()					\
	__asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory")

#define __atomic_release_fence()					\
	__asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory")

static __inline__ int arch_atomic_read(const atomic_t *v)
{
	int t;

	/* -mprefixed can generate offsets beyond range, fall back hack */
	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED))
		__asm__ __volatile__("lwz %0,0(%1)" : "=r"(t) : "b"(&v->counter));
	else
		__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter));

	return t;
}

static __inline__ void arch_atomic_set(atomic_t *v, int i)
{
	/* -mprefixed can generate offsets beyond range, fall back hack */
	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED))
		__asm__ __volatile__("stw %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter));
	else
		__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i));
}

#define ATOMIC_OP(op, asm_op, suffix, sign, ...)			\
static __inline__ void arch_atomic_##op(int a, atomic_t *v)		\
{									\
	int t;								\
									\
	__asm__ __volatile__(						\
"1:	lwarx	%0,0,%3		# atomic_" #op "\n"			\
	#asm_op "%I2" suffix " %0,%0,%2\n"				\
"	stwcx.	%0,0,%3 \n"						\
"	bne-	1b\n"							\
	: "=&r" (t), "+m" (v->counter)					\
	: "r"#sign (a), "r" (&v->counter)				\
	: "cc", ##__VA_ARGS__);						\
}									\

#define ATOMIC_OP_RETURN_RELAXED(op, asm_op, suffix, sign, ...)		\
static inline int arch_atomic_##op##_return_relaxed(int a, atomic_t *v)	\
{									\
	int t;								\
									\
	__asm__ __volatile__(						\
"1:	lwarx	%0,0,%3		# atomic_" #op "_return_relaxed\n"	\
	#asm_op "%I2" suffix " %0,%0,%2\n"				\
"	stwcx.	%0,0,%3\n"						\
"	bne-	1b\n"							\
	: "=&r" (t), "+m" (v->counter)					\
	: "r"#sign (a), "r" (&v->counter)				\
	: "cc", ##__VA_ARGS__);						\
									\
	return t;							\
}

#define ATOMIC_FETCH_OP_RELAXED(op, asm_op, suffix, sign, ...)		\
static inline int arch_atomic_fetch_##op##_relaxed(int a, atomic_t *v)	\
{									\
	int res, t;							\
									\
	__asm__ __volatile__(						\
"1:	lwarx	%0,0,%4		# atomic_fetch_" #op "_relaxed\n"	\
	#asm_op "%I3" suffix " %1,%0,%3\n"				\
"	stwcx.	%1,0,%4\n"						\
"	bne-	1b\n"							\
	: "=&r" (res), "=&r" (t), "+m" (v->counter)			\

Annotation

Implementation Notes