On Sun, Apr 28, 2019 at 8:58 AM Waiman Long longman@redhat.com wrote:
/* 2nd pass */
list_for_each_entry(waiter, &wlist, list) {
This is not safe, as far as I can tell.
As this loop walks the list, you do that
smp_store_release(&waiter->task, NULL);
and that very action means that the "waiter" is now released, and you cannot possibly use it.
HOWEVER.
"list_for_each_entry()" will load "waiter->next" to go forward in the list.
So you absolutely *have* to use "list_for_each_entry_safe()" in this loop, I think. You should treat that "smp_store_release()" as if you deleted the list entry, because you cannot trust it after you've done it, because the sleeper may have gone its own merry ways and released the on-stack 'waiter' allocation.
It's the *first* loop that you could play games with, because you hold the lock, and the list is stable during that loop. So the *first* loop could just walk the list, and then do one list splitting operation instead of doing that "list_move_tail()" thing for each entry.
But as long as you do "list_move_tail()" in the first loop, you'll obviously have to use list_for_each_entry_safe() there too, since right now you change that list as you walk it.
I'm just saying that you *could* optimize that first phase to just walk it and then perhaps split it with list_cut_before() when you find the first entry that isn't going to be woken up.
Linus