On Fri, 26 Feb 2021 14:24:29 -0800 Wei Wang wrote: > > I'm not sure this takes care of rapid: > > > > dev_set_threaded(0) > > # NAPI gets sent to sirq > > dev_set_threaded(1) > > > > since subsequent set_threaded(1) doesn't spawn the thread "afresh". > > I think the race between softirq and kthread could be purely dependent > on the SCHED bit. In napi_schedule_prep(), we check if SCHED bit is > set. And we only call ____napi_schedule() when SCHED bit is not set. > In ____napi_schedule(), we either wake up kthread, or raise softirq, > never both. > So as long as we don't wake up the kthread when creating it, there > should not be a chance of race between softirq and kthread.
But we don't destroy the thread when dev_set_threaded(0) is called, or make sure that it gets parked, we just clear NAPI_STATE_THREADED and that's it. The thread could be running long after NAPI_STATE_THREADED was cleared, and long after it gave up NAPI_STATE_SCHED. E.g. if some heavy sirq processing kicks in at the very moment we reenable BH. > > > while (!kthread_should_stop() && !napi_disable_pending(napi)) { > > > - if (test_bit(NAPI_STATE_SCHED, &napi->state)) { > > > + unsigned long val = READ_ONCE(napi->state); > > > + > > > + if (val & NAPIF_STATE_SCHED && > > > + !(val & NAPIF_STATE_SCHED_BUSY_POLL)) { > > > > Again, not protected from the napi_disable() case AFAICT. > > Hmmm..... Yes. I think you are right. I missed that napi_disable() > also grabs the SCHED bit. In this case, I think we have to use the > SCHED_THREADED bit. The SCHED_BUSY_POLL bit is not enough to protect > the race between napi_disable() and napi_threaded_poll(). :( > Sorry, I missed this point when evaluating both solutions. I will have > to switch to use the SCHED_THREADED bit. Alright, AFAICT SCHED_THREADED doesn't suffer either of the problems I brought up here.