]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - include/asm-x86_64/futex.h
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
[linux-2.6-omap-h63xx.git] / include / asm-x86_64 / futex.h
index 4f4cb3410d0698b694437d66c68628804214170a..5cdfb08013c38889dc8a42a2dff4c4a3c1833ff8 100644 (file)
@@ -55,7 +55,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
-       inc_preempt_count();
+       pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
@@ -78,7 +78,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
                ret = -ENOSYS;
        }
 
-       dec_preempt_count();
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {
@@ -95,9 +95,30 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 {
-       return -ENOSYS;
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       __asm__ __volatile__(
+               "1:     " LOCK_PREFIX "cmpxchgl %3, %1          \n"
+
+               "2:     .section .fixup, \"ax\"                 \n"
+               "3:     mov     %2, %0                          \n"
+               "       jmp     2b                              \n"
+               "       .previous                               \n"
+
+               "       .section __ex_table, \"a\"              \n"
+               "       .align  8                               \n"
+               "       .quad   1b,3b                           \n"
+               "       .previous                               \n"
+
+               : "=a" (oldval), "=m" (*uaddr)
+               : "i" (-EFAULT), "r" (newval), "0" (oldval)
+               : "memory"
+       );
+
+       return oldval;
 }
 
 #endif