arch/mips/include/asm/atomic.h

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

File Facts

System
Linux kernel
Corpus path
arch/mips/include/asm/atomic.h
Extension
.h
Size
8015 bytes
Lines
259
Domain
Architecture Layer
Bucket
arch/mips
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_ATOMIC_H
#define _ASM_ATOMIC_H

#include <linux/irqflags.h>
#include <linux/types.h>
#include <asm/asm.h>
#include <asm/barrier.h>
#include <asm/compiler.h>
#include <asm/cpu-features.h>
#include <asm/cmpxchg.h>
#include <asm/sync.h>

#define ATOMIC_OPS(pfx, type)						\
static __always_inline type arch_##pfx##_read(const pfx##_t *v)		\
{									\
	return READ_ONCE(v->counter);					\
}									\
									\
static __always_inline void arch_##pfx##_set(pfx##_t *v, type i)	\
{									\
	WRITE_ONCE(v->counter, i);					\
}									\

ATOMIC_OPS(atomic, int)

#ifdef CONFIG_64BIT
# define ATOMIC64_INIT(i)	{ (i) }
ATOMIC_OPS(atomic64, s64)
#endif

#define ATOMIC_OP(pfx, op, type, c_op, asm_op, ll, sc)			\
static __inline__ void arch_##pfx##_##op(type i, pfx##_t * v)		\
{									\
	type temp;							\
									\
	if (!kernel_uses_llsc) {					\
		unsigned long flags;					\
									\
		raw_local_irq_save(flags);				\
		v->counter c_op i;					\
		raw_local_irq_restore(flags);				\
		return;							\
	}								\
									\
	__asm__ __volatile__(						\
	"	.set	push					\n"	\
	"	.set	" MIPS_ISA_LEVEL "			\n"	\
	"	" __SYNC(full, loongson3_war) "			\n"	\
	"1:	" #ll "	%0, %1		# " #pfx "_" #op "	\n"	\
	"	" #asm_op " %0, %2				\n"	\
	"	" #sc "	%0, %1					\n"	\
	"\t" __stringify(SC_BEQZ) "	%0, 1b			\n"	\
	"	.set	pop					\n"	\
	: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)		\
	: "Ir" (i) : __LLSC_CLOBBER);					\
}

#define ATOMIC_OP_RETURN(pfx, op, type, c_op, asm_op, ll, sc)		\
static __inline__ type							\
arch_##pfx##_##op##_return_relaxed(type i, pfx##_t * v)			\
{									\
	type temp, result;						\
									\
	if (!kernel_uses_llsc) {					\
		unsigned long flags;					\
									\
		raw_local_irq_save(flags);				\
		result = v->counter;					\
		result c_op i;						\
		v->counter = result;					\
		raw_local_irq_restore(flags);				\
		return result;						\
	}								\
									\
	__asm__ __volatile__(						\
	"	.set	push					\n"	\
	"	.set	" MIPS_ISA_LEVEL "			\n"	\
	"	" __SYNC(full, loongson3_war) "			\n"	\
	"1:	" #ll "	%1, %2		# " #pfx "_" #op "_return\n"	\
	"	" #asm_op " %0, %1, %3				\n"	\
	"	" #sc "	%0, %2					\n"	\
	"\t" __stringify(SC_BEQZ) "	%0, 1b			\n"	\
	"	" #asm_op " %0, %1, %3				\n"	\
	"	.set	pop					\n"	\
	: "=&r" (result), "=&r" (temp),					\
	  "+" GCC_OFF_SMALL_ASM() (v->counter)				\
	: "Ir" (i) : __LLSC_CLOBBER);					\
									\
	return result;							\
}

Annotation

Implementation Notes