arch/s390/include/asm/atomic_ops.h

Source file repositories/reference/linux-study-clean/arch/s390/include/asm/atomic_ops.h

File Facts

System
Linux kernel
Corpus path
arch/s390/include/asm/atomic_ops.h
Extension
.h
Size
7302 bytes
Lines
246
Domain
Architecture Layer
Bucket
arch/s390
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 __ARCH_S390_ATOMIC_OPS__
#define __ARCH_S390_ATOMIC_OPS__

#include <linux/limits.h>
#include <asm/march.h>
#include <asm/asm.h>

static __always_inline int __atomic_read(const int *ptr)
{
	int val;

	asm volatile(
		"	l	%[val],%[ptr]"
		: [val] "=d" (val) : [ptr] "R" (*ptr));
	return val;
}

static __always_inline void __atomic_set(int *ptr, int val)
{
	if (__builtin_constant_p(val) && val >= S16_MIN && val <= S16_MAX) {
		asm volatile(
			"	mvhi	%[ptr],%[val]"
			: [ptr] "=Q" (*ptr) : [val] "K" (val));
	} else {
		asm volatile(
			"	st	%[val],%[ptr]"
			: [ptr] "=R" (*ptr) : [val] "d" (val));
	}
}

static __always_inline long __atomic64_read(const long *ptr)
{
	long val;

	asm volatile(
		"	lg	%[val],%[ptr]"
		: [val] "=d" (val) : [ptr] "RT" (*ptr));
	return val;
}

static __always_inline void __atomic64_set(long *ptr, long val)
{
	if (__builtin_constant_p(val) && val >= S16_MIN && val <= S16_MAX) {
		asm volatile(
			"	mvghi	%[ptr],%[val]"
			: [ptr] "=Q" (*ptr) : [val] "K" (val));
	} else {
		asm volatile(
			"	stg	%[val],%[ptr]"
			: [ptr] "=RT" (*ptr) : [val] "d" (val));
	}
}

#ifdef MARCH_HAS_Z196_FEATURES

#define __ATOMIC_OP(op_name, op_type, op_string, op_barrier)		\
static __always_inline op_type op_name(op_type val, op_type *ptr)	\
{									\
	op_type old;							\
									\
	asm volatile(							\
		op_string "	%[old],%[val],%[ptr]"			\
		op_barrier						\
		: [old] "=d" (old), [ptr] "+QS" (*ptr)			\
		: [val] "d" (val) : "cc", "memory");			\
	return old;							\
}									\

#define __ATOMIC_OPS(op_name, op_type, op_string)			\
	__ATOMIC_OP(op_name, op_type, op_string, "")			\
	__ATOMIC_OP(op_name##_barrier, op_type, op_string, "\nbcr 14,0")

__ATOMIC_OPS(__atomic_add, int, "laa")
__ATOMIC_OPS(__atomic_and, int, "lan")
__ATOMIC_OPS(__atomic_or,  int, "lao")
__ATOMIC_OPS(__atomic_xor, int, "lax")

__ATOMIC_OPS(__atomic64_add, long, "laag")
__ATOMIC_OPS(__atomic64_and, long, "lang")
__ATOMIC_OPS(__atomic64_or,  long, "laog")
__ATOMIC_OPS(__atomic64_xor, long, "laxg")

#undef __ATOMIC_OPS
#undef __ATOMIC_OP

#define __ATOMIC_CONST_OP(op_name, op_type, op_string, op_barrier)	\
static __always_inline void op_name(op_type val, op_type *ptr)		\
{									\
	asm volatile(							\
		op_string "	%[ptr],%[val]"				\

Annotation

Implementation Notes