mirror of https://gitee.com/openkylin/linux.git
rcu: Revert "Allow post-unlock reference for rt_mutex" to avoid priority-inversion
The patchdfeb9765ce
("Allow post-unlock reference for rt_mutex") ensured rcu-boost safe even the rt_mutex has post-unlock reference. But rt_mutex allowing post-unlock reference is definitely a bug and it was fixed by the commit27e35715df
("rtmutex: Plug slow unlock race"). This fix made the previous patch (dfeb9765ce
) useless. And even worse, the priority-inversion introduced by the the previous patch still exists. rcu_read_unlock_special() { rt_mutex_unlock(&rnp->boost_mtx); /* Priority-Inversion: * the current task had been deboosted and preempted as a low * priority task immediately, it could wait long before reschedule in, * and the rcu-booster also waits on this low priority task and sleeps. * This priority-inversion makes rcu-booster can't work * as expected. */ complete(&rnp->boost_completion); } Just revert the patch to avoid it. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
3ba4d0e09b
commit
abaf3f9d27
|
@ -172,11 +172,6 @@ struct rcu_node {
|
||||||
/* queued on this rcu_node structure that */
|
/* queued on this rcu_node structure that */
|
||||||
/* are blocking the current grace period, */
|
/* are blocking the current grace period, */
|
||||||
/* there can be no such task. */
|
/* there can be no such task. */
|
||||||
struct completion boost_completion;
|
|
||||||
/* Used to ensure that the rt_mutex used */
|
|
||||||
/* to carry out the boosting is fully */
|
|
||||||
/* released with no future boostee accesses */
|
|
||||||
/* before that rt_mutex is re-initialized. */
|
|
||||||
struct rt_mutex boost_mtx;
|
struct rt_mutex boost_mtx;
|
||||||
/* Used only for the priority-boosting */
|
/* Used only for the priority-boosting */
|
||||||
/* side effect, not as a lock. */
|
/* side effect, not as a lock. */
|
||||||
|
|
|
@ -429,10 +429,8 @@ void rcu_read_unlock_special(struct task_struct *t)
|
||||||
|
|
||||||
#ifdef CONFIG_RCU_BOOST
|
#ifdef CONFIG_RCU_BOOST
|
||||||
/* Unboost if we were boosted. */
|
/* Unboost if we were boosted. */
|
||||||
if (drop_boost_mutex) {
|
if (drop_boost_mutex)
|
||||||
rt_mutex_unlock(&rnp->boost_mtx);
|
rt_mutex_unlock(&rnp->boost_mtx);
|
||||||
complete(&rnp->boost_completion);
|
|
||||||
}
|
|
||||||
#endif /* #ifdef CONFIG_RCU_BOOST */
|
#endif /* #ifdef CONFIG_RCU_BOOST */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1081,15 +1079,11 @@ static int rcu_boost(struct rcu_node *rnp)
|
||||||
*/
|
*/
|
||||||
t = container_of(tb, struct task_struct, rcu_node_entry);
|
t = container_of(tb, struct task_struct, rcu_node_entry);
|
||||||
rt_mutex_init_proxy_locked(&rnp->boost_mtx, t);
|
rt_mutex_init_proxy_locked(&rnp->boost_mtx, t);
|
||||||
init_completion(&rnp->boost_completion);
|
|
||||||
raw_spin_unlock_irqrestore(&rnp->lock, flags);
|
raw_spin_unlock_irqrestore(&rnp->lock, flags);
|
||||||
/* Lock only for side effect: boosts task t's priority. */
|
/* Lock only for side effect: boosts task t's priority. */
|
||||||
rt_mutex_lock(&rnp->boost_mtx);
|
rt_mutex_lock(&rnp->boost_mtx);
|
||||||
rt_mutex_unlock(&rnp->boost_mtx); /* Then keep lockdep happy. */
|
rt_mutex_unlock(&rnp->boost_mtx); /* Then keep lockdep happy. */
|
||||||
|
|
||||||
/* Wait for boostee to be done w/boost_mtx before reinitializing. */
|
|
||||||
wait_for_completion(&rnp->boost_completion);
|
|
||||||
|
|
||||||
return ACCESS_ONCE(rnp->exp_tasks) != NULL ||
|
return ACCESS_ONCE(rnp->exp_tasks) != NULL ||
|
||||||
ACCESS_ONCE(rnp->boost_tasks) != NULL;
|
ACCESS_ONCE(rnp->boost_tasks) != NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue