diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-13 08:01:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-13 08:01:41 -0700 |
commit | 63b98080daa35f0d682db04f4fb7ada010888752 (patch) | |
tree | 213e124c89a51bbb99dd8e07fb6eacc970bbdc99 /include/asm-powerpc/futex.h | |
parent | 1883c5aba9973331e3ff0050e05707fe8e84fe0d (diff) | |
parent | eeac5c142b8687e35780b11b54b4c2f95b1a2436 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
[POWERPC] Fix G5 DART (IOMMU) race causing occasional data corruption
[POWERPC] Fix MMIO ops to provide expected barrier behaviour
[POWERPC] Fix interrupt clearing in kdump shutdown sequence
[POWERPC] update prep_defconfig
[POWERPC] kdump: Support kernels having 64k page size.
[POWERPC] Implement PowerPC futex_atomic_cmpxchg_inatomic().
[POWERPC] Add new, missing argument to of_irq_map_raw() for 86xx.
[POWERPC] Update defconfigs
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 f1b3c00bc1c..936422e5489 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__ */ |