Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Futexes for MIPS, for the time being only the R10000_LLSC_WAR version.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+50
+50
include/asm-mips/futex.h
··· 3 3 4 4 #ifdef __KERNEL__ 5 5 6 + #include <linux/config.h> 6 7 #include <linux/futex.h> 7 8 #include <asm/errno.h> 8 9 #include <asm/uaccess.h> 10 + 11 + #ifdef CONFIG_SMP 12 + #define __FUTEX_SMP_SYNC " sync \n" 13 + #else 14 + #define __FUTEX_SMP_SYNC 15 + #endif 16 + 17 + #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 18 + { \ 19 + __asm__ __volatile__( \ 20 + " .set push \n" \ 21 + " .set noat \n" \ 22 + " .set mips3 \n" \ 23 + "1: ll %1, (%3) # __futex_atomic_op1 \n" \ 24 + " .set mips0 \n" \ 25 + " " insn " \n" \ 26 + " .set mips3 \n" \ 27 + "2: sc $1, (%3) \n" \ 28 + " beqzl $1, 1b \n" \ 29 + __FUTEX_SMP_SYNC \ 30 + "3: \n" \ 31 + " .set pop \n" \ 32 + " .set mips0 \n" \ 33 + " .section .fixup,\"ax\" \n" \ 34 + "4: li %0, %5 \n" \ 35 + " j 2b \n" \ 36 + " .previous \n" \ 37 + " .section __ex_table,\"a\" \n" \ 38 + " "__UA_ADDR "\t1b, 4b \n" \ 39 + " "__UA_ADDR "\t2b, 4b \n" \ 40 + " .previous \n" \ 41 + : "=r" (ret), "=r" (oldval) \ 42 + : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ 43 + } 9 44 10 45 static inline int 11 46 futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ··· 60 25 61 26 switch (op) { 62 27 case FUTEX_OP_SET: 28 + __futex_atomic_op("move $1, %z4", ret, oldval, uaddr, oparg); 29 + break; 30 + 63 31 case FUTEX_OP_ADD: 32 + __futex_atomic_op("addu $1, %1, %z4", 33 + ret, oldval, uaddr, oparg); 34 + break; 64 35 case FUTEX_OP_OR: 36 + __futex_atomic_op("or $1, %1, %z4", 37 + ret, oldval, uaddr, oparg); 38 + break; 65 39 case FUTEX_OP_ANDN: 40 + __futex_atomic_op("and $1, %1, %z4", 41 + ret, oldval, uaddr, ~oparg); 42 + break; 66 43 case FUTEX_OP_XOR: 44 + __futex_atomic_op("xor $1, %1, %z4", 45 + ret, oldval, uaddr, oparg); 46 + break; 67 47 default: 68 48 ret = -ENOSYS; 69 49 }