Commit c3854a05 authored by Paul E. McKenney's avatar Paul E. McKenney

rcu: Pull rcu_gp_kthread() FQS loop into separate function

The rcu_gp_kthread() function is long and deeply indented, so this
commit pulls the loop that repeatedly invokes rcu_gp_fqs() into a new
rcu_gp_fqs_loop() function.
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
parent 4e95020c
...@@ -1976,6 +1976,71 @@ static void rcu_gp_fqs(bool first_time) ...@@ -1976,6 +1976,71 @@ static void rcu_gp_fqs(bool first_time)
} }
} }
/*
* Loop doing repeated quiescent-state forcing until the grace period ends.
*/
static void rcu_gp_fqs_loop(void)
{
bool first_gp_fqs;
int gf;
unsigned long j;
int ret;
struct rcu_node *rnp = rcu_get_root();
first_gp_fqs = true;
j = jiffies_till_first_fqs;
ret = 0;
for (;;) {
if (!ret) {
rcu_state.jiffies_force_qs = jiffies + j;
WRITE_ONCE(rcu_state.jiffies_kick_kthreads,
jiffies + 3 * j);
}
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqswait"));
rcu_state.gp_state = RCU_GP_WAIT_FQS;
ret = swait_event_idle_timeout_exclusive(
rcu_state.gp_wq, rcu_gp_fqs_check_wake(&gf), j);
rcu_state.gp_state = RCU_GP_DOING_FQS;
/* Locking provides needed memory barriers. */
/* If grace period done, leave loop. */
if (!READ_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp))
break;
/* If time for quiescent-state forcing, do it. */
if (ULONG_CMP_GE(jiffies, rcu_state.jiffies_force_qs) ||
(gf & RCU_GP_FLAG_FQS)) {
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqsstart"));
rcu_gp_fqs(first_gp_fqs);
first_gp_fqs = false;
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqsend"));
cond_resched_tasks_rcu_qs();
WRITE_ONCE(rcu_state.gp_activity, jiffies);
ret = 0; /* Force full wait till next FQS. */
j = jiffies_till_next_fqs;
} else {
/* Deal with stray signal. */
cond_resched_tasks_rcu_qs();
WRITE_ONCE(rcu_state.gp_activity, jiffies);
WARN_ON(signal_pending(current));
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqswaitsig"));
ret = 1; /* Keep old FQS timing. */
j = jiffies;
if (time_after(jiffies, rcu_state.jiffies_force_qs))
j = 1;
else
j = rcu_state.jiffies_force_qs - j;
}
}
}
/* /*
* Clean up after the old grace period. * Clean up after the old grace period.
*/ */
...@@ -2066,12 +2131,6 @@ static void rcu_gp_cleanup(void) ...@@ -2066,12 +2131,6 @@ static void rcu_gp_cleanup(void)
*/ */
static int __noreturn rcu_gp_kthread(void *unused) static int __noreturn rcu_gp_kthread(void *unused)
{ {
bool first_gp_fqs;
int gf;
unsigned long j;
int ret;
struct rcu_node *rnp = rcu_get_root();
rcu_bind_gp_kthread(); rcu_bind_gp_kthread();
for (;;) { for (;;) {
...@@ -2097,59 +2156,7 @@ static int __noreturn rcu_gp_kthread(void *unused) ...@@ -2097,59 +2156,7 @@ static int __noreturn rcu_gp_kthread(void *unused)
} }
/* Handle quiescent-state forcing. */ /* Handle quiescent-state forcing. */
first_gp_fqs = true; rcu_gp_fqs_loop();
j = jiffies_till_first_fqs;
ret = 0;
for (;;) {
if (!ret) {
rcu_state.jiffies_force_qs = jiffies + j;
WRITE_ONCE(rcu_state.jiffies_kick_kthreads,
jiffies + 3 * j);
}
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqswait"));
rcu_state.gp_state = RCU_GP_WAIT_FQS;
ret = swait_event_idle_timeout_exclusive(rcu_state.gp_wq,
rcu_gp_fqs_check_wake(&gf), j);
rcu_state.gp_state = RCU_GP_DOING_FQS;
/* Locking provides needed memory barriers. */
/* If grace period done, leave loop. */
if (!READ_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp))
break;
/* If time for quiescent-state forcing, do it. */
if (ULONG_CMP_GE(jiffies, rcu_state.jiffies_force_qs) ||
(gf & RCU_GP_FLAG_FQS)) {
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqsstart"));
rcu_gp_fqs(first_gp_fqs);
first_gp_fqs = false;
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqsend"));
cond_resched_tasks_rcu_qs();
WRITE_ONCE(rcu_state.gp_activity, jiffies);
ret = 0; /* Force full wait till next FQS. */
j = jiffies_till_next_fqs;
} else {
/* Deal with stray signal. */
cond_resched_tasks_rcu_qs();
WRITE_ONCE(rcu_state.gp_activity, jiffies);
WARN_ON(signal_pending(current));
trace_rcu_grace_period(rcu_state.name,
READ_ONCE(rcu_state.gp_seq),
TPS("fqswaitsig"));
ret = 1; /* Keep old FQS timing. */
j = jiffies;
if (time_after(jiffies,
rcu_state.jiffies_force_qs))
j = 1;
else
j = rcu_state.jiffies_force_qs - j;
}
}
/* Handle grace-period end. */ /* Handle grace-period end. */
rcu_state.gp_state = RCU_GP_CLEANUP; rcu_state.gp_state = RCU_GP_CLEANUP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment