arch/mips/include/asm/futex.h

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

File Facts

System
Linux kernel
Corpus path
arch/mips/include/asm/futex.h
Extension
.h
Size
5557 bytes
Lines
211
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_FUTEX_H
#define _ASM_FUTEX_H

#ifdef __KERNEL__

#include <linux/futex.h>
#include <linux/uaccess.h>
#include <asm/asm-eva.h>
#include <asm/barrier.h>
#include <asm/compiler.h>
#include <asm/errno.h>
#include <asm/sync.h>

#define arch_futex_atomic_op_inuser arch_futex_atomic_op_inuser
#define futex_atomic_cmpxchg_inatomic futex_atomic_cmpxchg_inatomic
#include <asm-generic/futex.h>

#define __futex_atomic_op(op, insn, ret, oldval, uaddr, oparg)		\
{									\
	if (cpu_has_llsc && IS_ENABLED(CONFIG_WAR_R10000_LLSC)) {	\
		__asm__ __volatile__(					\
		"	.set	push				\n"	\
		"	.set	noat				\n"	\
		"	.set	push				\n"	\
		"	.set	arch=r4000			\n"	\
		"1:	ll	%1, %4	# __futex_atomic_op	\n"	\
		"	.set	pop				\n"	\
		"	" insn	"				\n"	\
		"	.set	arch=r4000			\n"	\
		"2:	sc	$1, %2				\n"	\
		"	beqzl	$1, 1b				\n"	\
		__stringify(__WEAK_LLSC_MB) "			\n"	\
		"3:						\n"	\
		"	.insn					\n"	\
		"	.set	pop				\n"	\
		"	.section .fixup,\"ax\"			\n"	\
		"4:	li	%0, %6				\n"	\
		"	j	3b				\n"	\
		"	.previous				\n"	\
		"	.section __ex_table,\"a\"		\n"	\
		"	"__UA_ADDR "\t1b, 4b			\n"	\
		"	"__UA_ADDR "\t2b, 4b			\n"	\
		"	.previous				\n"	\
		: "=r" (ret), "=&r" (oldval),				\
		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
		  "i" (-EFAULT)						\
		: "memory");						\
	} else if (cpu_has_llsc) {					\
		__asm__ __volatile__(					\
		"	.set	push				\n"	\
		"	.set	noat				\n"	\
		"	.set	push				\n"	\
		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
		"	" __SYNC(full, loongson3_war) "		\n"	\
		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
		"	.set	pop				\n"	\
		"	" insn	"				\n"	\
		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
		"2:	"user_sc("$1", "%2")"			\n"	\
		"	beqz	$1, 1b				\n"	\
		__stringify(__WEAK_LLSC_MB) "			\n"	\
		"3:						\n"	\
		"	.insn					\n"	\
		"	.set	pop				\n"	\
		"	.section .fixup,\"ax\"			\n"	\
		"4:	li	%0, %6				\n"	\
		"	j	3b				\n"	\
		"	.previous				\n"	\
		"	.section __ex_table,\"a\"		\n"	\
		"	"__UA_ADDR "\t1b, 4b			\n"	\
		"	"__UA_ADDR "\t2b, 4b			\n"	\
		"	.previous				\n"	\
		: "=r" (ret), "=&r" (oldval),				\
		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
		  "i" (-EFAULT)						\
		: "memory");						\
	} else {							\
		/* fallback for non-SMP */				\
		ret = futex_atomic_op_inuser_local(op, oparg, oval, uaddr);	\
	}								\
}

static inline int
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
	int oldval = 0, ret;

	if (!access_ok(uaddr, sizeof(u32)))

Annotation

Implementation Notes