arch/s390/include/asm/cmpxchg.h

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

File Facts

System
Linux kernel
Corpus path
arch/s390/include/asm/cmpxchg.h
Extension
.h
Size
6239 bytes
Lines
274
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 __ASM_CMPXCHG_H
#define __ASM_CMPXCHG_H

#include <linux/mmdebug.h>
#include <linux/types.h>
#include <linux/bug.h>
#include <asm/asm.h>

void __cmpxchg_called_with_bad_pointer(void);

static __always_inline u32 __cs_asm(u64 ptr, u32 old, u32 new)
{
	asm volatile(
		"	cs	%[old],%[new],%[ptr]"
		: [old] "+d" (old), [ptr] "+Q" (*(u32 *)ptr)
		: [new] "d" (new)
		: "memory", "cc");
	return old;
}

static __always_inline u64 __csg_asm(u64 ptr, u64 old, u64 new)
{
	asm volatile(
		"	csg	%[old],%[new],%[ptr]"
		: [old] "+d" (old), [ptr] "+QS" (*(u64 *)ptr)
		: [new] "d" (new)
		: "memory", "cc");
	return old;
}

static __no_sanitize_or_inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new)
{
	union {
		u8 b[4];
		u32 w;
	} old32, new32;
	u32 prev;
	int i;

	i = ptr & 3;
	ptr &= ~0x3;
	prev = READ_ONCE(*(u32 *)ptr);
	do {
		old32.w = prev;
		if (old32.b[i] != old)
			return old32.b[i];
		new32.w = old32.w;
		new32.b[i] = new;
		prev = __cs_asm(ptr, old32.w, new32.w);
	} while (prev != old32.w);
	return old;
}

static __no_sanitize_or_inline u16 __arch_cmpxchg2(u64 ptr, u16 old, u16 new)
{
	union {
		u16 b[2];
		u32 w;
	} old32, new32;
	u32 prev;
	int i;

	i = (ptr & 3) >> 1;
	ptr &= ~0x3;
	prev = READ_ONCE(*(u32 *)ptr);
	do {
		old32.w = prev;
		if (old32.b[i] != old)
			return old32.b[i];
		new32.w = old32.w;
		new32.b[i] = new;
		prev = __cs_asm(ptr, old32.w, new32.w);
	} while (prev != old32.w);
	return old;
}

static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size)
{
	switch (size) {
	case 1:	 return __arch_cmpxchg1(ptr, old & 0xff, new & 0xff);
	case 2:  return __arch_cmpxchg2(ptr, old & 0xffff, new & 0xffff);
	case 4:  return __cs_asm(ptr, old & 0xffffffff, new & 0xffffffff);
	case 8:  return __csg_asm(ptr, old, new);
	default: __cmpxchg_called_with_bad_pointer();
	}
	return old;
}

#define arch_cmpxchg(ptr, o, n)						\
({									\

Annotation

Implementation Notes