On Mon, Feb 15, 2021 at 12:23:52PM -0300, André Almeida wrote:

> +static int futex_dequeue_multiple(struct futexv_head *futexv, unsigned int 
> nr)
> +{
> +     int i, ret = -1;
> +
> +     for (i = 0; i < nr; i++) {
> +             spin_lock(&futexv->objects[i].bucket->lock);
> +             if (!list_empty_careful(&futexv->objects[i].list)) {
> +                     list_del_init_careful(&futexv->objects[i].list);
> +                     bucket_dec_waiters(futexv->objects[i].bucket);

What's with the careful? AFAICT all sites have that bucket->lock.

> +             } else {
> +                     ret = i;
> +             }
> +             spin_unlock(&futexv->objects[i].bucket->lock);
> +     }
> +
> +     return ret;
> +}

> +static int futex_enqueue(struct futexv_head *futexv, unsigned int nr_futexes,
> +                      int *awakened)
> +{
> +     int i, ret;
> +     u32 uval, *uaddr, val;
> +     struct futex_bucket *bucket;
> +
> +retry:
> +     set_current_state(TASK_INTERRUPTIBLE);
> +
> +     for (i = 0; i < nr_futexes; i++) {
> +             uaddr = (u32 * __user)futexv->objects[i].uaddr;
> +             val = (u32)futexv->objects[i].val;
> +
> +             bucket = futexv->objects[i].bucket;
> +
> +             bucket_inc_waiters(bucket);
> +             spin_lock(&bucket->lock);
> +
> +             ret = futex_get_user(&uval, uaddr);
> +
> +             if (unlikely(ret)) {
> +                     spin_unlock(&bucket->lock);
> +
> +                     bucket_dec_waiters(bucket);
> +                     __set_current_state(TASK_RUNNING);
> +                     *awakened = futex_dequeue_multiple(futexv, i);
> +
> +                     if (__get_user(uval, uaddr))
> +                             return -EFAULT;
> +
> +                     if (*awakened >= 0)
> +                             return 1;
> +
> +                     goto retry;
> +             }
> +
> +             if (uval != val) {
> +                     spin_unlock(&bucket->lock);
> +
> +                     bucket_dec_waiters(bucket);
> +                     __set_current_state(TASK_RUNNING);
> +                     *awakened = futex_dequeue_multiple(futexv, i);
> +
> +                     if (*awakened >= 0)
> +                             return 1;
> +
> +                     return -EAGAIN;
> +             }
> +
> +             list_add_tail(&futexv->objects[i].list, &bucket->list);

and here

> +             spin_unlock(&bucket->lock);
> +     }
> +
> +     return 0;
> +}
> +

> +static void futex_mark_wake(struct futex_waiter *waiter,
> +                         struct futex_bucket *bucket,
> +                         struct wake_q_head *wake_q)
> +{
> +     struct task_struct *task;
> +     struct futexv_head *parent = futex_get_parent((uintptr_t)waiter,
> +                                                   waiter->index);
> +

        lockdep_assert_held(&bucket->lock);

> +     parent->hint = true;
> +     task = parent->task;
> +     get_task_struct(task);
> +     list_del_init_careful(&waiter->list);

and here

> +     wake_q_add_safe(wake_q, task);
> +     bucket_dec_waiters(bucket);
> +}

Reply via email to