futex.h 1.8 KB
Newer Older
K
Kaz Kojima 已提交
1 2
#ifndef __ASM_SH_FUTEX_H
#define __ASM_SH_FUTEX_H
3

K
Kaz Kojima 已提交
4
#ifdef __KERNEL__
5

K
Kaz Kojima 已提交
6
#include <linux/futex.h>
7
#include <linux/uaccess.h>
K
Kaz Kojima 已提交
8 9 10 11 12
#include <asm/errno.h>

/* XXX: UP variants, fix for SH-4A and SMP.. */
#include <asm/futex-irq.h>

13
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
K
Kaz Kojima 已提交
14 15 16 17 18 19 20 21 22 23
{
	int op = (encoded_op >> 28) & 7;
	int cmp = (encoded_op >> 24) & 15;
	int oparg = (encoded_op << 8) >> 20;
	int cmparg = (encoded_op << 20) >> 20;
	int oldval = 0, ret;

	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
		oparg = 1 << oparg;

24
	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
K
Kaz Kojima 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
		return -EFAULT;

	pagefault_disable();

	switch (op) {
	case FUTEX_OP_SET:
		ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
		break;
	case FUTEX_OP_ADD:
		ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
		break;
	case FUTEX_OP_OR:
		ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
		break;
	case FUTEX_OP_ANDN:
		ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
		break;
	case FUTEX_OP_XOR:
		ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
		break;
	default:
		ret = -ENOSYS;
		break;
	}

	pagefault_enable();

	if (!ret) {
		switch (cmp) {
		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
		default: ret = -ENOSYS;
		}
	}

	return ret;
}

static inline int
68 69
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
			      u32 oldval, u32 newval)
K
Kaz Kojima 已提交
70
{
71
	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
K
Kaz Kojima 已提交
72 73
		return -EFAULT;

74
	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
K
Kaz Kojima 已提交
75 76 77 78
}

#endif /* __KERNEL__ */
#endif /* __ASM_SH_FUTEX_H */