[PATCH (updated)]: PTHREAD_PRIO_INHERIT support for ARM.
From: Remy Bohmer
Date: Fri Jul 27 2007 - 11:37:53 EST
Hello All,
Attached I have put a (very simple) patch to make PTHREAD_PRIO_INHERIT
work for ARM.
This patch implements the futex_atomic_cmpxchg_inatomic() for the
ARM architecture. Without this patch the userland PI mutex will
not work on ARM.
I have tested it with pi_stress, classic_pi and our production
environment, on the following Cores:
* Atmel at91rm9200 (ARM-v4)
* Atmel at91sam9261 (ARM-v5)
But it should also work on other ARM cores (like ARM-v6), because it
makes use of a cmpxchg() routine that was already there in the kernel
and that was optimised for pre- and post- ARM-v6 cores. But even if it
doesn't work, it could not make it worse than the current
implementation, that one is completely broken, it allows multiple
threads in the same protected section. So, with this patch it can only
get better ;-)
Coding style checked with checkpatch.pl 0.6 on 2.6.22.1-rt6
So, Please apply.
Kind Regards,
Remy Böhmer
PTHREAD_PRIO_INHERIT support for ARM.
This patch implements the futex_atomic_cmpxchg_inatomic() for the
ARM architecture. Without this patch the userland PI mutex will
not work.
Signed-off-by: Remy Bohmer <linux@xxxxxxxxxx>
---
# include/asm-arm/futex.h | 64 +++++++++++++++++++++++++++++++++++++++++++++---
# 1 file changed, 61 insertions(+), 3 deletions(-)
#
Index: linux-2.6.22/include/asm-arm/futex.h
===================================================================
--- linux-2.6.22.orig/include/asm-arm/futex.h 2007-07-09 01:32:17.000000000 +0200
+++ linux-2.6.22/include/asm-arm/futex.h 2007-07-24 17:05:26.000000000 +0200
@@ -1,6 +1,64 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_ARM_FUTEX_H
+#define _ASM_ARM_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
+#include <linux/futex.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <asm/atomic.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;
+ int 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ default:
+ ret = -ENOSYS;
+ }
+
+ 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 cmpxchg(uaddr, oldval, newval);
+}
+
+#endif
#endif