1 #ifndef __ASM_SH_FUTEX_H 2 #define __ASM_SH_FUTEX_H 3 4 #ifdef __KERNEL__ 5 6 #include <linux/futex.h> 7 #include <linux/uaccess.h> 8 #include <asm/errno.h> 9 10 /* XXX: UP variants, fix for SH-4A and SMP.. */ 11 #include <asm/futex-irq.h> 12 13 static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 14 { 15 int op = (encoded_op >> 28) & 7; 16 int cmp = (encoded_op >> 24) & 15; 17 int oparg = (encoded_op << 8) >> 20; 18 int cmparg = (encoded_op << 20) >> 20; 19 int oldval = 0, ret; 20 21 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 22 oparg = 1 << oparg; 23 24 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 25 return -EFAULT; 26 27 pagefault_disable(); 28 29 switch (op) { 30 case FUTEX_OP_SET: 31 ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); 32 break; 33 case FUTEX_OP_ADD: 34 ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); 35 break; 36 case FUTEX_OP_OR: 37 ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); 38 break; 39 case FUTEX_OP_ANDN: 40 ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); 41 break; 42 case FUTEX_OP_XOR: 43 ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); 44 break; 45 default: 46 ret = -ENOSYS; 47 break; 48 } 49 50 pagefault_enable(); 51 52 if (!ret) { 53 switch (cmp) { 54 case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; 55 case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; 56 case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; 57 case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; 58 case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; 59 case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; 60 default: ret = -ENOSYS; 61 } 62 } 63 64 return ret; 65 } 66 67 static inline int 68 futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 69 { 70 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 71 return -EFAULT; 72 73 return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval); 74 } 75 76 #endif /* __KERNEL__ */ 77 #endif /* __ASM_SH_FUTEX_H */ 78