When config preempt RCU,  and then  there are multiple levels  node,  the 
current task is preempted  in rcu  read critical region.
the current task be add to "rnp->blkd_tasks" link list,  and the 
"rnp->gp_tasks"  may be assigned a value .  these rnp is leaf node in RCU tree.

But in "rcu_gp_fqs_loop" func, we check blocked readers in root node. 

static void rcu_gp_fqs_loop(void)
 {
            .....
            struct rcu_node *rnp = rcu_get_root();
            .....
            if (!READ_ONCE(rnp->qsmask) &&
                               !rcu_preempt_blocked_readers_cgp(rnp))    
------> rnp is root node
                     break;
            ....
}

the root node's blkd_tasks never add task, the "rnp->gp_tasks" is never be 
assigned value,  this check is invailed.
 Should we check leaf nodes like this 

--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1846,6 +1846,25 @@ static bool rcu_gp_init(void)
        return true;
 }
 
+static bool rcu_preempt_blocked_readers(void)
+{
+       struct rcu_node *rnp;
+       unsigned long flags;
+       bool ret = false;
+
+       rcu_for_each_leaf_node(rnp) {
+               raw_spin_lock_irqsave_rcu_node(rnp, flags);
+               if (rcu_preempt_blocked_readers_cgp(rnp)) {
+                       ret = true;
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+                       break;
+               }
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+       }
+
+       return ret;
+}
+
 /*
  * Helper function for swait_event_idle_exclusive() wakeup at 
force-quiescent-state
  * time.
@@ -1864,7 +1883,7 @@ static bool rcu_gp_fqs_check_wake(int *gfp)
                return true;
 
        // The current grace period has completed.
-       if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers_cgp(rnp))
+       if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers())
                return true;
 
        return false;
@@ -1927,7 +1946,7 @@ static void rcu_gp_fqs_loop(void)
                /* Locking provides needed memory barriers. */
                /* If grace period done, leave loop. */
                if (!READ_ONCE(rnp->qsmask) &&
-                   !rcu_preempt_blocked_readers_cgp(rnp))
+                   !rcu_preempt_blocked_readers())
                        break;
                /* If time for quiescent-state forcing, do it. */
                if (!time_after(rcu_state.jiffies_force_qs, jiffies) ||
-- 


thanks
Qiang

Reply via email to