Skip to content

Commit 8f870e6

Browse files
committed
srcu: Block less aggressively for expedited grace periods
Commit 282d899 ("srcu: Prevent expedited GPs and blocking readers from consuming CPU") fixed a problem where a long-running expedited SRCU grace period could block kernel live patching. It did so by giving up on expediting once a given SRCU expedited grace period grew too old. Unfortunately, this added excessive delays to boots of virtual embedded systems specifying "-bios QEMU_EFI.fd" to qemu. This commit therefore makes the transition away from expediting less aggressive, increasing the per-grace-period phase number of non-sleeping polls of readers from one to three and increasing the required grace-period age from one jiffy (actually from zero to one jiffies) to two jiffies (actually from one to two jiffies). Fixes: 282d899 ("srcu: Prevent expedited GPs and blocking readers from consuming CPU") Signed-off-by: Paul E. McKenney <[email protected]> Reported-by: Zhangfei Gao <[email protected]> Reported-by: chenxiang (M)" <[email protected]> Cc: Shameerali Kolothum Thodi <[email protected]> Cc: Paolo Bonzini <[email protected]> Reviewed-by: Neeraj Upadhyay <[email protected]> Link: https://lore.kernel.org/all/[email protected]/
1 parent a111daf commit 8f870e6

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

kernel/rcu/srcutree.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ static bool srcu_readers_active(struct srcu_struct *ssp)
513513

514514
#define SRCU_INTERVAL 1 // Base delay if no expedited GPs pending.
515515
#define SRCU_MAX_INTERVAL 10 // Maximum incremental delay from slow readers.
516-
#define SRCU_MAX_NODELAY_PHASE 1 // Maximum per-GP-phase consecutive no-delay instances.
516+
#define SRCU_MAX_NODELAY_PHASE 3 // Maximum per-GP-phase consecutive no-delay instances.
517517
#define SRCU_MAX_NODELAY 100 // Maximum consecutive no-delay instances.
518518

519519
/*
@@ -522,16 +522,22 @@ static bool srcu_readers_active(struct srcu_struct *ssp)
522522
*/
523523
static unsigned long srcu_get_delay(struct srcu_struct *ssp)
524524
{
525+
unsigned long gpstart;
526+
unsigned long j;
525527
unsigned long jbase = SRCU_INTERVAL;
526528

527529
if (ULONG_CMP_LT(READ_ONCE(ssp->srcu_gp_seq), READ_ONCE(ssp->srcu_gp_seq_needed_exp)))
528530
jbase = 0;
529-
if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)))
530-
jbase += jiffies - READ_ONCE(ssp->srcu_gp_start);
531-
if (!jbase) {
532-
WRITE_ONCE(ssp->srcu_n_exp_nodelay, READ_ONCE(ssp->srcu_n_exp_nodelay) + 1);
533-
if (READ_ONCE(ssp->srcu_n_exp_nodelay) > SRCU_MAX_NODELAY_PHASE)
534-
jbase = 1;
531+
if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq))) {
532+
j = jiffies - 1;
533+
gpstart = READ_ONCE(ssp->srcu_gp_start);
534+
if (time_after(j, gpstart))
535+
jbase += j - gpstart;
536+
if (!jbase) {
537+
WRITE_ONCE(ssp->srcu_n_exp_nodelay, READ_ONCE(ssp->srcu_n_exp_nodelay) + 1);
538+
if (READ_ONCE(ssp->srcu_n_exp_nodelay) > SRCU_MAX_NODELAY_PHASE)
539+
jbase = 1;
540+
}
535541
}
536542
return jbase > SRCU_MAX_INTERVAL ? SRCU_MAX_INTERVAL : jbase;
537543
}

0 commit comments

Comments
 (0)