The whole lock/set IRQ_INPROGRESS/unlock path can then only happen
before the locked section above, in which case we see and wait nicely
and all is good, or after, in which case the store to foo will be
visible to the IRQ handler as it will be ordered with the unlock in the
code above.
Note that napi_synchronize needs a slightly different treatement.
Here, the situation boils down to:
one CPU does:
foo = 1;
while(test_bit(bar))
barrier();
and the other:
if (!test_and_set_bit(bar)) {
read & use foo
smp_mb__before_clear_bit();
clear_bit(bar);
}
The good thing here is that read & use foo is part of the critical
section (I hate hand-made locks ...) defined by bar which makes
things somewhat easier than the synchronize_irq() case.
I think a simple smp_mb(); here after foo = 1; is enough, which means
basically just having an smp_mp(); inside napi_synchronize(), before
the test_bit(). Or do I miss something ?
Cheers,
Ben.