diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-09-19 00:42:13 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-19 00:42:13 -0400 |
commit | 4a3381feb823e06c8e2da7e283c17b0b6fdbddcf (patch) | |
tree | e1bef4c3db854bb10fd13dc67415d77b5d999533 /include/asm-powerpc/futex.h | |
parent | fea63e38013ec628ab3f7fddc4c2148064b7910a (diff) | |
parent | 47a5c6fa0e204a2b63309c648bb2fde36836c826 (diff) | |
download | linux-4a3381feb823e06c8e2da7e283c17b0b6fdbddcf.tar.bz2 |
Merge branch 'master' into upstream
Diffstat (limited to 'include/asm-powerpc/futex.h')
-rw-r--r-- | include/asm-powerpc/futex.h | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index f1b3c00bc1ce..936422e54891 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h @@ -84,7 +84,33 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { - return -ENOSYS; + int prev; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + __asm__ __volatile__ ( + LWSYNC_ON_SMP +"1: lwarx %0,0,%2 # futex_atomic_cmpxchg_inatomic\n\ + cmpw 0,%0,%3\n\ + bne- 3f\n" + PPC405_ERR77(0,%2) +"2: stwcx. %4,0,%2\n\ + bne- 1b\n" + ISYNC_ON_SMP +"3: .section .fixup,\"ax\"\n\ +4: li %0,%5\n\ + b 3b\n\ + .previous\n\ + .section __ex_table,\"a\"\n\ + .align 3\n\ + " PPC_LONG "1b,4b,2b,4b\n\ + .previous" \ + : "=&r" (prev), "+m" (*uaddr) + : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT) + : "cc", "memory"); + + return prev; } #endif /* __KERNEL__ */ |