diff options
Diffstat (limited to 'kernel/rcu/tree_plugin.h')
| -rw-r--r-- | kernel/rcu/tree_plugin.h | 25 | 
1 files changed, 16 insertions, 9 deletions
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index c6ea81cd4189..097635c41135 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -56,6 +56,8 @@ static void __init rcu_bootup_announce_oddness(void)  		pr_info("\tBoot-time adjustment of callback high-water mark to %ld.\n", qhimark);  	if (qlowmark != DEFAULT_RCU_QLOMARK)  		pr_info("\tBoot-time adjustment of callback low-water mark to %ld.\n", qlowmark); +	if (qovld != DEFAULT_RCU_QOVLD) +		pr_info("\tBoot-time adjustment of callback overload level to %ld.\n", qovld);  	if (jiffies_till_first_fqs != ULONG_MAX)  		pr_info("\tBoot-time adjustment of first FQS scan delay to %ld jiffies.\n", jiffies_till_first_fqs);  	if (jiffies_till_next_fqs != ULONG_MAX) @@ -753,7 +755,7 @@ dump_blkd_tasks(struct rcu_node *rnp, int ncheck)  	raw_lockdep_assert_held_rcu_node(rnp);  	pr_info("%s: grp: %d-%d level: %d ->gp_seq %ld ->completedqs %ld\n",  		__func__, rnp->grplo, rnp->grphi, rnp->level, -		(long)rnp->gp_seq, (long)rnp->completedqs); +		(long)READ_ONCE(rnp->gp_seq), (long)rnp->completedqs);  	for (rnp1 = rnp; rnp1; rnp1 = rnp1->parent)  		pr_info("%s: %d:%d ->qsmask %#lx ->qsmaskinit %#lx ->qsmaskinitnext %#lx\n",  			__func__, rnp1->grplo, rnp1->grphi, rnp1->qsmask, rnp1->qsmaskinit, rnp1->qsmaskinitnext); @@ -1032,18 +1034,18 @@ static int rcu_boost_kthread(void *arg)  	trace_rcu_utilization(TPS("Start boost kthread@init"));  	for (;;) { -		rnp->boost_kthread_status = RCU_KTHREAD_WAITING; +		WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_WAITING);  		trace_rcu_utilization(TPS("End boost kthread@rcu_wait"));  		rcu_wait(rnp->boost_tasks || rnp->exp_tasks);  		trace_rcu_utilization(TPS("Start boost kthread@rcu_wait")); -		rnp->boost_kthread_status = RCU_KTHREAD_RUNNING; +		WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_RUNNING);  		more2boost = rcu_boost(rnp);  		if (more2boost)  			spincnt++;  		else  			spincnt = 0;  		if (spincnt > 10) { -			rnp->boost_kthread_status = RCU_KTHREAD_YIELDING; +			WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_YIELDING);  			trace_rcu_utilization(TPS("End boost kthread@rcu_yield"));  			schedule_timeout_interruptible(2);  			trace_rcu_utilization(TPS("Start boost kthread@rcu_yield")); @@ -1077,12 +1079,12 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)  	    (rnp->gp_tasks != NULL &&  	     rnp->boost_tasks == NULL &&  	     rnp->qsmask == 0 && -	     ULONG_CMP_GE(jiffies, rnp->boost_time))) { +	     (ULONG_CMP_GE(jiffies, rnp->boost_time) || rcu_state.cbovld))) {  		if (rnp->exp_tasks == NULL)  			rnp->boost_tasks = rnp->gp_tasks;  		raw_spin_unlock_irqrestore_rcu_node(rnp, flags);  		rcu_wake_cond(rnp->boost_kthread_task, -			      rnp->boost_kthread_status); +			      READ_ONCE(rnp->boost_kthread_status));  	} else {  		raw_spin_unlock_irqrestore_rcu_node(rnp, flags);  	} @@ -1486,6 +1488,7 @@ module_param(nocb_nobypass_lim_per_jiffy, int, 0);   * flag the contention.   */  static void rcu_nocb_bypass_lock(struct rcu_data *rdp) +	__acquires(&rdp->nocb_bypass_lock)  {  	lockdep_assert_irqs_disabled();  	if (raw_spin_trylock(&rdp->nocb_bypass_lock)) @@ -1529,6 +1532,7 @@ static bool rcu_nocb_bypass_trylock(struct rcu_data *rdp)   * Release the specified rcu_data structure's ->nocb_bypass_lock.   */  static void rcu_nocb_bypass_unlock(struct rcu_data *rdp) +	__releases(&rdp->nocb_bypass_lock)  {  	lockdep_assert_irqs_disabled();  	raw_spin_unlock(&rdp->nocb_bypass_lock); @@ -1577,8 +1581,7 @@ static void rcu_nocb_unlock_irqrestore(struct rcu_data *rdp,  static void rcu_lockdep_assert_cblist_protected(struct rcu_data *rdp)  {  	lockdep_assert_irqs_disabled(); -	if (rcu_segcblist_is_offloaded(&rdp->cblist) && -	    cpu_online(rdp->cpu)) +	if (rcu_segcblist_is_offloaded(&rdp->cblist))  		lockdep_assert_held(&rdp->nocb_lock);  } @@ -1930,6 +1933,7 @@ static void nocb_gp_wait(struct rcu_data *my_rdp)  	struct rcu_data *rdp;  	struct rcu_node *rnp;  	unsigned long wait_gp_seq = 0; // Suppress "use uninitialized" warning. +	bool wasempty = false;  	/*  	 * Each pass through the following loop checks for CBs and for the @@ -1969,10 +1973,13 @@ static void nocb_gp_wait(struct rcu_data *my_rdp)  		     rcu_seq_done(&rnp->gp_seq, cur_gp_seq))) {  			raw_spin_lock_rcu_node(rnp); /* irqs disabled. */  			needwake_gp = rcu_advance_cbs(rnp, rdp); +			wasempty = rcu_segcblist_restempty(&rdp->cblist, +							   RCU_NEXT_READY_TAIL);  			raw_spin_unlock_rcu_node(rnp); /* irqs disabled. */  		}  		// Need to wait on some grace period? -		WARN_ON_ONCE(!rcu_segcblist_restempty(&rdp->cblist, +		WARN_ON_ONCE(wasempty && +			     !rcu_segcblist_restempty(&rdp->cblist,  						      RCU_NEXT_READY_TAIL));  		if (rcu_segcblist_nextgp(&rdp->cblist, &cur_gp_seq)) {  			if (!needwait_gp ||  |