* Process a futex-list entry, check whether it's owned by the
* dying task, and do notification if so:
*/
-int handle_futex_death(unsigned int *uaddr, struct task_struct *curr)
+int handle_futex_death(u32 __user *uaddr, struct task_struct *curr)
{
- unsigned int futex_val;
+ u32 uval;
-repeat:
- if (get_user(futex_val, uaddr))
+retry:
+ if (get_user(uval, uaddr))
return -1;
- if ((futex_val & FUTEX_TID_MASK) == curr->pid) {
+ if ((uval & FUTEX_TID_MASK) == curr->pid) {
/*
* Ok, this dying thread is truly holding a futex
* of interest. Set the OWNER_DIED bit atomically
* thread-death.) The rest of the cleanup is done in
* userspace.
*/
- if (futex_atomic_cmpxchg_inuser(uaddr, futex_val,
- futex_val | FUTEX_OWNER_DIED) !=
- futex_val)
- goto repeat;
+ if (futex_atomic_cmpxchg_inatomic(uaddr, uval,
+ uval | FUTEX_OWNER_DIED) != uval)
+ goto retry;
- if (futex_val & FUTEX_WAITERS)
+ if (uval & FUTEX_WAITERS)
futex_wake((unsigned long)uaddr, 1);
}
return 0;
if (handle_futex_death((void *)entry + futex_offset,
curr))
return;
-
/*
* Fetch the next entry in the list:
*/
unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
int val2 = 0;
- if ((op == FUTEX_WAIT) && utime) {
+ if (utime && (op == FUTEX_WAIT)) {
if (copy_from_user(&t, utime, sizeof(t)) != 0)
return -EFAULT;
+ if (!timespec_valid(&t))
+ return -EINVAL;
timeout = timespec_to_jiffies(&t) + 1;
}
/*
(unsigned long)uaddr2, val2, val3);
}
-static struct super_block *
-futexfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static int futexfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data,
+ struct vfsmount *mnt)
{
- return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA);
+ return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt);
}
static struct file_system_type futex_fs_type = {