summaryrefslogtreecommitdiffstats
path: root/arch/sh/include/asm/futex.h
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-08-07 10:55:03 +0200
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-08-07 10:55:03 +0200
commit4fb8af10d0fd09372d52966b76922b9e82bbc950 (patch)
treed240e4d40357583e3f3eb228dccf20122a5b31ed /arch/sh/include/asm/futex.h
parent[ARM] Add support for arch/arm/mach-*/include and arch/arm/plat-*/include (diff)
parentkbuild: a better way to generate cscope database change (diff)
downloadlinux-4fb8af10d0fd09372d52966b76922b9e82bbc950.tar.xz
linux-4fb8af10d0fd09372d52966b76922b9e82bbc950.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes
Diffstat (limited to 'arch/sh/include/asm/futex.h')
-rw-r--r--arch/sh/include/asm/futex.h77
1 files changed, 77 insertions, 0 deletions
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
new file mode 100644
index 000000000000..68256ec5fa35
--- /dev/null
+++ b/arch/sh/include/asm/futex.h
@@ -0,0 +1,77 @@
+#ifndef __ASM_SH_FUTEX_H
+#define __ASM_SH_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+/* XXX: UP variants, fix for SH-4A and SMP.. */
+#include <asm/futex-irq.h>
+
+static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+ 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;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ 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
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_FUTEX_H */