rcu_gp_kthread_wake(rsp);
}
+/*
+ * Read from the jiffies_till_next_fqs boot/sysfs parameter, applying
+ * limits and updating as needed.
+ */
+static unsigned long read_jiffies_till_next_fqs(void)
+{
+ unsigned long j;
+
+ j = jiffies_till_next_fqs;
+ if (j > HZ)
+ j = jiffies_till_next_fqs = HZ;
+ else if (j < 1)
+ j = jiffies_till_next_fqs = 1;
+ return j;
+}
+
/*
* Initialize a new grace period. Return 0 if no grace period required.
*/
ACCESS_ONCE(rsp->gpnum),
TPS("fqswaitsig"));
}
- j = jiffies_till_next_fqs;
- if (j > HZ) {
- j = HZ;
- jiffies_till_next_fqs = HZ;
- } else if (j < 1) {
- j = 1;
- jiffies_till_next_fqs = 1;
- }
+ j = read_jiffies_till_next_fqs();
}
/* Handle grace-period end. */
{
int c, cl;
bool firsttime = 1;
+ unsigned long gp_next_start = jiffies;
+ unsigned long j;
struct rcu_head *list;
struct rcu_head *next;
struct rcu_head **tail;
/* Each pass through this loop invokes one batch of callbacks */
for (;;) {
+ /* Avoid excessive wakeups due to short grace periods. */
+ j = jiffies;
+ if (time_before(j, gp_next_start))
+ schedule_timeout_uninterruptible(gp_next_start - j);
+
/* If not polling, wait for next batch of callbacks. */
if (!rcu_nocb_poll) {
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
firsttime = 1;
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
TPS("WokeNonEmpty"));
+ /*
+ * Time of next grace-period start. The idea is that
+ * we are willing to take a jiffies_till_next_fqs delay
+ * if any CPUs are idle, so we should be willing to take
+ * a similar delay when all are busy context-switching
+ * their little brains out.
+ */
+ gp_next_start = jiffies + read_jiffies_till_next_fqs();
/*
* Extract queued callbacks, update counts, and wait