On Fri, Nov 29, 2019 at 04:45:35PM +0100, Sebastian Andrzej Siewior wrote: > On 2019-11-25 12:25:45 [-0500], Steven Rostedt wrote: > > On Fri, 22 Nov 2019 19:01:40 +0100 > > Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> wrote: > > > > > Let me give you an example how I got into this: > > > > > > do_sigaction() acquires p->sighand->siglock and then iterates over list > > > via for_each_thread() which is a list_for_each_entry_rcu(). No RCU lock > > > is held, just the siglock. > > > On removal side, __unhash_process() removes a task from the list but > > > while doing so it holds the siglock and tasklist_lock. So it is > > > perfectly fine. > > > Later, we have: > > > |do_exit() > > > | -> exit_notify() > > > | -> write_lock_irq(&tasklist_lock); > > > | -> forget_original_parent() > > > | -> find_child_reaper() > > > | -> find_alive_thread() > > > | -> for_each_thread() > > > > > > find_alive_thread() does the for_each_thread() and checks PF_EXITING. > > > it might be enough for not operating on "removed" task_struct. It > > > dereferences task_struct->flags while looking for PF_EXITING. At this > > > point only tasklist_lock is acquired. > > > I have *no* idea if the whole synchronisation based on siglock/ > > > PF_EXITING/ tasklist_lock is enough and RCU simply doesn't matter. It > > > seems so. > > > > > > I am a little worried if this construct here (or somewhere else) assumes > > > that holding one of those locks, which disable preemption, is the same > > > as rcu_read_lock() (or rcu_read_lock_sched()). > > > > I'm wondering if instead, we should start throwing in rcu_read_lock() > > and explicitly have the preempt disabled rcu use that as well, since > > today it's basically one and the same. > > Any comment from the RCU camp on this? > Maybe just adding the missing RCU annotation for the list annotation is > enough (like if lock X or Y is held then everything fine). !RT gets this > implicit via preempt_disable(). I'm just worried if someone expects > this kind of behaviour. > If I remember correctly, Scott added rcu_read_lock() recently to > local_bh_disable() because RCU-torture expected it. Adding an explicit rcu_read_lock()/rcu_read_unlock() pair to the various spinlock primitives for -rt seems quite sensible to me. My guess is that non-rt CONFIG_PREEMPT=y uses in mainline might not like the extra overhead. For the trylock primitives, would it make more sense to do the rcu_read_lock() only after successful acquisition, or to do the rcu_read_lock() to begin with and then do rcu_read_unlock() upon failure? I would guess the latter, but don't feel strongly about it. Thanx, Paul