xref: /linux/arch/parisc/include/asm/futex.h (revision deae26bf6a10e47983606f5df080b91e97650ead)
1*deae26bfSKyle McMartin #ifndef _ASM_PARISC_FUTEX_H
2*deae26bfSKyle McMartin #define _ASM_PARISC_FUTEX_H
3*deae26bfSKyle McMartin 
4*deae26bfSKyle McMartin #ifdef __KERNEL__
5*deae26bfSKyle McMartin 
6*deae26bfSKyle McMartin #include <linux/futex.h>
7*deae26bfSKyle McMartin #include <linux/uaccess.h>
8*deae26bfSKyle McMartin #include <asm/errno.h>
9*deae26bfSKyle McMartin 
10*deae26bfSKyle McMartin static inline int
11*deae26bfSKyle McMartin futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
12*deae26bfSKyle McMartin {
13*deae26bfSKyle McMartin 	int op = (encoded_op >> 28) & 7;
14*deae26bfSKyle McMartin 	int cmp = (encoded_op >> 24) & 15;
15*deae26bfSKyle McMartin 	int oparg = (encoded_op << 8) >> 20;
16*deae26bfSKyle McMartin 	int cmparg = (encoded_op << 20) >> 20;
17*deae26bfSKyle McMartin 	int oldval = 0, ret;
18*deae26bfSKyle McMartin 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
19*deae26bfSKyle McMartin 		oparg = 1 << oparg;
20*deae26bfSKyle McMartin 
21*deae26bfSKyle McMartin 	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
22*deae26bfSKyle McMartin 		return -EFAULT;
23*deae26bfSKyle McMartin 
24*deae26bfSKyle McMartin 	pagefault_disable();
25*deae26bfSKyle McMartin 
26*deae26bfSKyle McMartin 	switch (op) {
27*deae26bfSKyle McMartin 	case FUTEX_OP_SET:
28*deae26bfSKyle McMartin 	case FUTEX_OP_ADD:
29*deae26bfSKyle McMartin 	case FUTEX_OP_OR:
30*deae26bfSKyle McMartin 	case FUTEX_OP_ANDN:
31*deae26bfSKyle McMartin 	case FUTEX_OP_XOR:
32*deae26bfSKyle McMartin 	default:
33*deae26bfSKyle McMartin 		ret = -ENOSYS;
34*deae26bfSKyle McMartin 	}
35*deae26bfSKyle McMartin 
36*deae26bfSKyle McMartin 	pagefault_enable();
37*deae26bfSKyle McMartin 
38*deae26bfSKyle McMartin 	if (!ret) {
39*deae26bfSKyle McMartin 		switch (cmp) {
40*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
41*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
42*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
43*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
44*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
45*deae26bfSKyle McMartin 		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
46*deae26bfSKyle McMartin 		default: ret = -ENOSYS;
47*deae26bfSKyle McMartin 		}
48*deae26bfSKyle McMartin 	}
49*deae26bfSKyle McMartin 	return ret;
50*deae26bfSKyle McMartin }
51*deae26bfSKyle McMartin 
52*deae26bfSKyle McMartin /* Non-atomic version */
53*deae26bfSKyle McMartin static inline int
54*deae26bfSKyle McMartin futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
55*deae26bfSKyle McMartin {
56*deae26bfSKyle McMartin 	int err = 0;
57*deae26bfSKyle McMartin 	int uval;
58*deae26bfSKyle McMartin 
59*deae26bfSKyle McMartin 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
60*deae26bfSKyle McMartin 	 * our gateway page, and causes no end of trouble...
61*deae26bfSKyle McMartin 	 */
62*deae26bfSKyle McMartin 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
63*deae26bfSKyle McMartin 		return -EFAULT;
64*deae26bfSKyle McMartin 
65*deae26bfSKyle McMartin 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
66*deae26bfSKyle McMartin 		return -EFAULT;
67*deae26bfSKyle McMartin 
68*deae26bfSKyle McMartin 	err = get_user(uval, uaddr);
69*deae26bfSKyle McMartin 	if (err) return -EFAULT;
70*deae26bfSKyle McMartin 	if (uval == oldval)
71*deae26bfSKyle McMartin 		err = put_user(newval, uaddr);
72*deae26bfSKyle McMartin 	if (err) return -EFAULT;
73*deae26bfSKyle McMartin 	return uval;
74*deae26bfSKyle McMartin }
75*deae26bfSKyle McMartin 
76*deae26bfSKyle McMartin #endif /*__KERNEL__*/
77*deae26bfSKyle McMartin #endif /*_ASM_PARISC_FUTEX_H*/
78