Boqun Feng <boqun.feng@xxxxxxxxx> writes: >> That said, `synchronize_rcu` is rather expensive and is not needed in >> all cases: If we have never registered a `poll_table` with the >> `wait_list`, then we don't need to call `synchronize_rcu`. (And this is >> a common case in Binder - not all processes use Binder with epoll.) The >> current implementation does not account for this, but we could change it >> to store a boolean next to the `wait_list` to keep track of whether a >> `poll_table` has ever been registered. It is up to discussion whether >> this is desireable. >> >> It is not clear to me whether we can implement the above without storing >> an extra boolean. We could check whether the `wait_list` is empty, but >> it is not clear that this is sufficient. Perhaps someone knows the >> answer? If a `poll_table` has previously been registered with a > > That won't be sufficient, considering this: > > CPU 0 CPU 1 > ep_remove_wait_queue(): > whead = smp_load_acquire(&pwq->whead); // whead is not NULL > PollCondVar::drop(): > self.inner.notify(): > <for each wait entry in the list> > ep_poll_callback(): > <remove wait entry> > smp_store_release(&ep_pwq_from_wait(wait)->whead, NULL); > <lock the waitqueue> > waitqueue_active() // return false, since the queue is emtpy > <unlock> > ... > <free the waitqueue> > if (whead) { > remove_wait_queue(whead, &pwq->wait); // Use-after-free BOOM! > } > > > Note that moving the `wait_list` empty checking before > `self.inner.notify()` won't change the result, since there might be a > `notify` called by users before `PollCondVar::drop()`, hence the same > result. > > Regards, > Boqun Thank you for confirming my suspicion. Alice