rcu: Drive quiescent-state-forcing delay from HZ
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Thu, 4 Apr 2013 05:14:11 +0000 (22:14 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 10 Jun 2013 20:44:56 +0000 (13:44 -0700)
Systems with HZ=100 can have slow bootup times due to the default
three-jiffy delays between quiescent-state forcing attempts.  This
commit therefore auto-tunes the RCU_JIFFIES_TILL_FORCE_QS value based
on the value of HZ.  However, this would break very large systems that
require more time between quiescent-state forcing attempts.  This
commit therefore also ups the default delay by one jiffy for each
256 CPUs that might be on the system (based off of nr_cpu_ids at
runtime, -not- NR_CPUS at build time).

Updated to collapse #ifdefs for RCU_JIFFIES_TILL_FORCE_QS into a
step-function definition as suggested by Josh Triplett.

Reported-by: Paul Mackerras <paulus@au1.ibm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/rcutree.c
kernel/rcutree.h

index 1009c0ccd4b186ebaf66740ac0f864b29e246b0f..f344d3c824a4afbc43c9dc8f6e6bbbb15ad2ed58 100644 (file)
@@ -218,8 +218,8 @@ module_param(blimit, long, 0444);
 module_param(qhimark, long, 0444);
 module_param(qlowmark, long, 0444);
 
-static ulong jiffies_till_first_fqs = RCU_JIFFIES_TILL_FORCE_QS;
-static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS;
+static ulong jiffies_till_first_fqs = ULONG_MAX;
+static ulong jiffies_till_next_fqs = ULONG_MAX;
 
 module_param(jiffies_till_first_fqs, ulong, 0644);
 module_param(jiffies_till_next_fqs, ulong, 0644);
@@ -3265,11 +3265,25 @@ static void __init rcu_init_one(struct rcu_state *rsp,
  */
 static void __init rcu_init_geometry(void)
 {
+       ulong d;
        int i;
        int j;
        int n = nr_cpu_ids;
        int rcu_capacity[MAX_RCU_LVLS + 1];
 
+       /*
+        * Initialize any unspecified boot parameters.
+        * The default values of jiffies_till_first_fqs and
+        * jiffies_till_next_fqs are set to the RCU_JIFFIES_TILL_FORCE_QS
+        * value, which is a function of HZ, then adding one for each
+        * RCU_JIFFIES_FQS_DIV CPUs that might be on the system.
+        */
+       d = RCU_JIFFIES_TILL_FORCE_QS + nr_cpu_ids / RCU_JIFFIES_FQS_DIV;
+       if (jiffies_till_first_fqs == ULONG_MAX)
+               jiffies_till_first_fqs = d;
+       if (jiffies_till_next_fqs == ULONG_MAX)
+               jiffies_till_next_fqs = d;
+
        /* If the compile-time values are accurate, just leave. */
        if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF &&
            nr_cpu_ids == NR_CPUS)
index 4df503470e420a24420edaf5d836d6aae508a155..4a39d364493cf66bf64c161d46c2bc3fd089978f 100644 (file)
@@ -343,12 +343,17 @@ struct rcu_data {
 #define RCU_FORCE_QS           3       /* Need to force quiescent state. */
 #define RCU_SIGNAL_INIT                RCU_SAVE_DYNTICK
 
-#define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
+#define RCU_JIFFIES_TILL_FORCE_QS (1 + (HZ > 250) + (HZ > 500))
+                                       /* For jiffies_till_first_fqs and */
+                                       /*  and jiffies_till_next_fqs. */
 
-#define RCU_STALL_RAT_DELAY            2       /* Allow other CPUs time */
-                                               /*  to take at least one */
-                                               /*  scheduling clock irq */
-                                               /*  before ratting on them. */
+#define RCU_JIFFIES_FQS_DIV    256     /* Very large systems need more */
+                                       /*  delay between bouts of */
+                                       /*  quiescent-state forcing. */
+
+#define RCU_STALL_RAT_DELAY    2       /* Allow other CPUs time to take */
+                                       /*  at least one scheduling clock */
+                                       /*  irq before ratting on them. */
 
 #define rcu_wait(cond)                                                 \
 do {                                                                   \