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); > +}