0001
0002 #ifndef _ASM_GENERIC_FUTEX_H
0003 #define _ASM_GENERIC_FUTEX_H
0004
0005 #include <linux/futex.h>
0006 #include <linux/uaccess.h>
0007 #include <asm/errno.h>
0008
0009 #ifndef futex_atomic_cmpxchg_inatomic
0010 #ifndef CONFIG_SMP
0011
0012
0013
0014
0015
0016 #define futex_atomic_cmpxchg_inatomic(uval, uaddr, oldval, newval) \
0017 futex_atomic_cmpxchg_inatomic_local(uval, uaddr, oldval, newval)
0018 #define arch_futex_atomic_op_inuser(op, oparg, oval, uaddr) \
0019 futex_atomic_op_inuser_local(op, oparg, oval, uaddr)
0020 #endif
0021 #endif
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 static inline int
0038 futex_atomic_op_inuser_local(int op, u32 oparg, int *oval, u32 __user *uaddr)
0039 {
0040 int oldval, ret;
0041 u32 tmp;
0042
0043 preempt_disable();
0044
0045 ret = -EFAULT;
0046 if (unlikely(get_user(oldval, uaddr) != 0))
0047 goto out_pagefault_enable;
0048
0049 ret = 0;
0050 tmp = oldval;
0051
0052 switch (op) {
0053 case FUTEX_OP_SET:
0054 tmp = oparg;
0055 break;
0056 case FUTEX_OP_ADD:
0057 tmp += oparg;
0058 break;
0059 case FUTEX_OP_OR:
0060 tmp |= oparg;
0061 break;
0062 case FUTEX_OP_ANDN:
0063 tmp &= ~oparg;
0064 break;
0065 case FUTEX_OP_XOR:
0066 tmp ^= oparg;
0067 break;
0068 default:
0069 ret = -ENOSYS;
0070 }
0071
0072 if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
0073 ret = -EFAULT;
0074
0075 out_pagefault_enable:
0076 preempt_enable();
0077
0078 if (ret == 0)
0079 *oval = oldval;
0080
0081 return ret;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static inline int
0099 futex_atomic_cmpxchg_inatomic_local(u32 *uval, u32 __user *uaddr,
0100 u32 oldval, u32 newval)
0101 {
0102 u32 val;
0103
0104 preempt_disable();
0105 if (unlikely(get_user(val, uaddr) != 0)) {
0106 preempt_enable();
0107 return -EFAULT;
0108 }
0109
0110 if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
0111 preempt_enable();
0112 return -EFAULT;
0113 }
0114
0115 *uval = val;
0116 preempt_enable();
0117
0118 return 0;
0119 }
0120
0121 #endif