Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.14-rc2 83 lines 2.0 kB view raw
1#ifndef _ASM_FUTEX_H 2#define _ASM_FUTEX_H 3 4#ifdef __KERNEL__ 5 6#include <linux/futex.h> 7#include <asm/errno.h> 8#include <asm/memory.h> 9#include <asm/uaccess.h> 10 11#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 12 __asm__ __volatile (SYNC_ON_SMP \ 13"1: lwarx %0,0,%2\n" \ 14 insn \ 15"2: stwcx. %1,0,%2\n\ 16 bne- 1b\n\ 17 li %1,0\n\ 183: .section .fixup,\"ax\"\n\ 194: li %1,%3\n\ 20 b 3b\n\ 21 .previous\n\ 22 .section __ex_table,\"a\"\n\ 23 .align 3\n\ 24 .llong 1b,4b,2b,4b\n\ 25 .previous" \ 26 : "=&r" (oldval), "=&r" (ret) \ 27 : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ 28 : "cr0", "memory") 29 30static inline int 31futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 32{ 33 int op = (encoded_op >> 28) & 7; 34 int cmp = (encoded_op >> 24) & 15; 35 int oparg = (encoded_op << 8) >> 20; 36 int cmparg = (encoded_op << 20) >> 20; 37 int oldval = 0, ret; 38 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 39 oparg = 1 << oparg; 40 41 if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) 42 return -EFAULT; 43 44 inc_preempt_count(); 45 46 switch (op) { 47 case FUTEX_OP_SET: 48 __futex_atomic_op("", ret, oldval, uaddr, oparg); 49 break; 50 case FUTEX_OP_ADD: 51 __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); 52 break; 53 case FUTEX_OP_OR: 54 __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); 55 break; 56 case FUTEX_OP_ANDN: 57 __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); 58 break; 59 case FUTEX_OP_XOR: 60 __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); 61 break; 62 default: 63 ret = -ENOSYS; 64 } 65 66 dec_preempt_count(); 67 68 if (!ret) { 69 switch (cmp) { 70 case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; 71 case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; 72 case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; 73 case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; 74 case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; 75 case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; 76 default: ret = -ENOSYS; 77 } 78 } 79 return ret; 80} 81 82#endif 83#endif