]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/futex.c
UBUNTU: [Config] CONFIG_PHY_CPCAP_USB=m
[mirror_ubuntu-artful-kernel.git] / kernel / futex.c
index a6639b3463733caa99a6f662b69cfbc59a97a9b8..b5270cfcfd8c673d9f3f52f4914830c7818bceb4 100644 (file)
@@ -1574,6 +1574,45 @@ out:
        return ret;
 }
 
+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
+{
+       unsigned int op =         (encoded_op & 0x70000000) >> 28;
+       unsigned int cmp =        (encoded_op & 0x0f000000) >> 24;
+       int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);
+       int cmparg = sign_extend32(encoded_op & 0x00000fff, 12);
+       int oldval, ret;
+
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
+               if (oparg < 0 || oparg > 31)
+                       return -EINVAL;
+               oparg = 1 << oparg;
+       }
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+               return -EFAULT;
+
+       ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
+       if (ret)
+               return ret;
+
+       switch (cmp) {
+       case FUTEX_OP_CMP_EQ:
+               return oldval == cmparg;
+       case FUTEX_OP_CMP_NE:
+               return oldval != cmparg;
+       case FUTEX_OP_CMP_LT:
+               return oldval < cmparg;
+       case FUTEX_OP_CMP_GE:
+               return oldval >= cmparg;
+       case FUTEX_OP_CMP_LE:
+               return oldval <= cmparg;
+       case FUTEX_OP_CMP_GT:
+               return oldval > cmparg;
+       default:
+               return -ENOSYS;
+       }
+}
+
 /*
  * Wake up all waiters hashed on the physical page that is mapped
  * to this virtual address: