rcutorture: Emulate userspace sojourn during call_rcu() floods
During an actual call_rcu() flood, there would be frequent trips to userspace (in-kernel call_rcu() floods must be otherwise housebroken). Userspace execution allows a great many things to interrupt execution, and rcutorture needs to also allow such interruptions. This commit therefore causes call_rcu() floods to occasionally invoke schedule(), thus preventing spurious rcutorture failures due to other parts of the kernel becoming irate at the call_rcu() flood events. Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
This commit is contained in:
Родитель
f4e8352928
Коммит
bd1bfc51a3
|
@ -1713,12 +1713,14 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the scheduler a chance, even on nohz_full CPUs.
|
// Give the scheduler a chance, even on nohz_full CPUs.
|
||||||
static void rcu_torture_fwd_prog_cond_resched(void)
|
static void rcu_torture_fwd_prog_cond_resched(unsigned long iter)
|
||||||
{
|
{
|
||||||
if (IS_ENABLED(CONFIG_PREEMPT) && IS_ENABLED(CONFIG_NO_HZ_FULL)) {
|
if (IS_ENABLED(CONFIG_PREEMPT) && IS_ENABLED(CONFIG_NO_HZ_FULL)) {
|
||||||
if (need_resched())
|
// Real call_rcu() floods hit userspace, so emulate that.
|
||||||
|
if (need_resched() || (iter & 0xfff))
|
||||||
schedule();
|
schedule();
|
||||||
} else {
|
} else {
|
||||||
|
// No userspace emulation: CB invocation throttles call_rcu()
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1746,7 +1748,7 @@ static unsigned long rcu_torture_fwd_prog_cbfree(void)
|
||||||
spin_unlock_irqrestore(&rcu_fwd_lock, flags);
|
spin_unlock_irqrestore(&rcu_fwd_lock, flags);
|
||||||
kfree(rfcp);
|
kfree(rfcp);
|
||||||
freed++;
|
freed++;
|
||||||
rcu_torture_fwd_prog_cond_resched();
|
rcu_torture_fwd_prog_cond_resched(freed);
|
||||||
}
|
}
|
||||||
return freed;
|
return freed;
|
||||||
}
|
}
|
||||||
|
@ -1790,7 +1792,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)
|
||||||
udelay(10);
|
udelay(10);
|
||||||
cur_ops->readunlock(idx);
|
cur_ops->readunlock(idx);
|
||||||
if (!fwd_progress_need_resched || need_resched())
|
if (!fwd_progress_need_resched || need_resched())
|
||||||
rcu_torture_fwd_prog_cond_resched();
|
rcu_torture_fwd_prog_cond_resched(1);
|
||||||
}
|
}
|
||||||
(*tested_tries)++;
|
(*tested_tries)++;
|
||||||
if (!time_before(jiffies, stopat) &&
|
if (!time_before(jiffies, stopat) &&
|
||||||
|
@ -1875,7 +1877,7 @@ static void rcu_torture_fwd_prog_cr(void)
|
||||||
rfcp->rfc_gps = 0;
|
rfcp->rfc_gps = 0;
|
||||||
}
|
}
|
||||||
cur_ops->call(&rfcp->rh, rcu_torture_fwd_cb_cr);
|
cur_ops->call(&rfcp->rh, rcu_torture_fwd_cb_cr);
|
||||||
rcu_torture_fwd_prog_cond_resched();
|
rcu_torture_fwd_prog_cond_resched(n_launders + n_max_cbs);
|
||||||
}
|
}
|
||||||
stoppedat = jiffies;
|
stoppedat = jiffies;
|
||||||
n_launders_cb_snap = READ_ONCE(n_launders_cb);
|
n_launders_cb_snap = READ_ONCE(n_launders_cb);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче