On 2021-09-22 13:10:12 [+0200], Frederic Weisbecker wrote: > On Wed, Sep 22, 2021 at 08:32:08AM +0200, Sebastian Andrzej Siewior wrote: > > On 2021-09-22 01:45:18 [+0200], Frederic Weisbecker wrote: > > > > > > Also while at it, I'm asking again: traditionally softirqs could assume that > > > manipulating a local state was safe against !irq_count() code fiddling with > > > the same state on the same CPU. > > > > > > Now with preemptible softirqs, that assumption can be broken anytime. RCU was > > > fortunate enough to have a warning for that. But who knows how many issues like > > > this are lurking? > > > > If "local state" is modified then it is safe as long as it is modified > > within a local_bh_disable() section. And we are in this section while > > invoking a forced-threaded interrupt. The special part about RCU is > > that it is used in_irq() as part of core-code. > > But local_bh_disable() was deemed for protecting from interrupting softirqs, > not the other way around (softirqs being preempted by other tasks). The latter > semantic is new and nobody had that in mind until softirqs have been made > preemptible. > > For example: > > CPU 0 > ----------------------------------------------- > SOFTIRQ RANDOM TASK > ------ ----------- > int *X = &per_cpu(CPUX, 0) int *X = &per_cpu(CPUX, 0) > int A, B; WRITE_ONCE(*X, 0); > WRITE_ONCE(*X, 1); > A = READ_ONCE(*X); > B = READ_ONCE(*X); > > > We used to have the guarantee that A == B. That's not true anymore. Now > some new explicit local_bh_disable() should be carefully placed on RANDOM_TASK > where it wasn't necessary before. RCU is not that special in this regard. The part with rcutree.use_softirq=0 on RT does not make it any better, right? So you rely on some implicit behaviour which breaks with RT such as: CPU 0 ----------------------------------------------- RANDOM TASK-A RANDOM TASK-B ------ ----------- int *X = &per_cpu(CPUX, 0) int *X = &per_cpu(CPUX, 0) int A, B; spin_lock(&D); spin_lock(&C); WRITE_ONCE(*X, 0); A = READ_ONCE(*X); WRITE_ONCE(*X, 1); B = READ_ONCE(*X); while spinlock C and D are just random locks not related to CPUX but it just happens that they are held at that time. So for !RT you guarantee that A == B while it is not the case on RT. Sebastian