On 01/25/2015 05:18 AM, Paul E. McKenney wrote: > > Good point! In my scenario, CPU 0 would not yet have switched away from > Task A. Hmmm... Yet Sasha really does see this failure. Will give it > some more thought. > > Any ideas?
I don't known which commit was merged from the rcu-git-tree in Sasha's test I try to review it. We can fallback to git-bitsect if the reviews fails. Thanks, Lai > > Thanx, Paul > >> Thanks, >> Lai >> >>> >>> 6. Once in rcu_read_unlock_special(), the fact that >>> current->rcu_read_unlock_special.b.need_qs is true becomes >>> apparent, so rcu_read_unlock_special() invokes rcu_preempt_qs(). >>> Recursively, given that we interrupted out of that same >>> function in the preceding step. >>> >>> 7. Because rcu_preempt_data.passed_quiesce is now true, >>> rcu_preempt_qs() does nothing, and simply returns. >>> >>> 8. Upon return to rcu_read_unlock_special(), it is noted that >>> current->rcu_read_unlock_special is still nonzero (because >>> the interrupted rcu_preempt_qs() had not yet gotten around >>> to clearing current->rcu_read_unlock_special.b.need_qs). >>> >>> 9. Execution proceeds to the WARN_ON_ONCE(), which notes that >>> we are in an interrupt handler and thus duly splats. >>> >>> The solution, as noted above, is to make rcu_read_unlock_special() >>> clear out current->rcu_read_unlock_special.b.need_qs after calling >>> rcu_preempt_qs(). The interrupted rcu_preempt_qs() will clear it again, >>> but this is harmless. The worst that happens is that we clobber another >>> attempt to set this field, but this is not a problem because we just >>> got done reporting a quiescent state. >>> >>> Reported-by: Sasha Levin <sasha.le...@oracle.com> >>> Signed-off-by: Paul E. McKenney <paul...@linux.vnet.ibm.com> >>> >>> diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h >>> index 8669de884445..ec99dc16aa38 100644 >>> --- a/kernel/rcu/tree_plugin.h >>> +++ b/kernel/rcu/tree_plugin.h >>> @@ -322,6 +322,7 @@ void rcu_read_unlock_special(struct task_struct *t) >>> special = t->rcu_read_unlock_special; >>> if (special.b.need_qs) { >>> rcu_preempt_qs(); >>> + t->rcu_read_unlock_special.need_qs = false; >>> if (!t->rcu_read_unlock_special.s) { >>> local_irq_restore(flags); >>> return; >>> >>> . >>> >> > > . > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/