On 07/05/26 11:09 am, Vishal Chourasia wrote:
On large idle systems, changing system-wide SMT level using the sysfs
control interface still takes approximately 40-55 minutes. Changing SMT
levels is a user triggered operation generally done when systems are
fairly idle. This causes users to be blocked from doing other subsequent
work.

Analyzing the collected profile data during SMT level switch, showed
that CPU hotplug machinery was blocked on synchronize_rcu() calls.

Expedite RCU grace periods for the entire duration of triggered SMT
switch operation via the sysfs control interface. Individual CPU hotplug
operations via the online/offline interface are not affected.

On a PPC64 system with 400 CPUs:

   SMT8 to SMT1:
     before:  1m14s
     after:   3.2s   (~23x faster)

   SMT1 to SMT8:
     before:  2m27s
     after:   2.5s   (~58x faster)

On a large config system with 1920 CPUs, completion time improves from
~1 hour to 5-6 minutes.
Hi Vishal,

I verified the patch on PPC64 system using the configuration described below.
Configuration:
    •    Kernel version: 7.1.0-rc2+
    •    Number of CPUs: 960

Using this setup, I evaluated the patch with both SMT enabled and SMT disabled. patch shows a significant improvement in the both SMT=on/off case.


SMT Mode    | Without Patch    | With Patch | % Improvement     |
-------------------------------------------------------------------
SMT=off     | 3m 56.174s       | 0m 34.284s | +85.48%           |
SMT=on      | 3m 47.322s       | 0m 35.583s | +84.35%           |


Regards,
Samir
Signed-off-by: Vishal Chourasia <[email protected]>
---
  include/linux/rcupdate.h | 8 ++++++++
  kernel/cpu.c             | 4 ++++
  kernel/rcu/rcu.h         | 4 ----
  3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index bfa765132de8..b6bccf131f1c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -1178,6 +1178,14 @@ rcu_head_after_call_rcu(struct rcu_head *rhp, 
rcu_callback_t f)
  extern int rcu_expedited;
  extern int rcu_normal;
+#ifdef CONFIG_TINY_RCU
+static inline void rcu_expedite_gp(void) { }
+static inline void rcu_unexpedite_gp(void) { }
+#else
+void rcu_expedite_gp(void);
+void rcu_unexpedite_gp(void);
+#endif
+
  DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock())
  DECLARE_LOCK_GUARD_0_ATTRS(rcu, __acquires_shared(RCU), 
__releases_shared(RCU))
diff --git a/kernel/cpu.c b/kernel/cpu.c
index bc4f7a9ba64e..6351da9dffdc 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2658,6 +2658,7 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
        int cpu, ret = 0;
cpu_maps_update_begin();
+       rcu_expedite_gp();
        for_each_online_cpu(cpu) {
                if (topology_is_primary_thread(cpu))
                        continue;
@@ -2687,6 +2688,7 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
        }
        if (!ret)
                cpu_smt_control = ctrlval;
+       rcu_unexpedite_gp();
        cpu_maps_update_done();
        return ret;
  }
@@ -2704,6 +2706,7 @@ int cpuhp_smt_enable(void)
        int cpu, ret = 0;
cpu_maps_update_begin();
+       rcu_expedite_gp();
        cpu_smt_control = CPU_SMT_ENABLED;
        for_each_present_cpu(cpu) {
                /* Skip online CPUs and CPUs on offline nodes */
@@ -2717,6 +2720,7 @@ int cpuhp_smt_enable(void)
                /* See comment in cpuhp_smt_disable() */
                cpuhp_online_cpu_device(cpu);
        }
+       rcu_unexpedite_gp();
        cpu_maps_update_done();
        return ret;
  }
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index fa6d30ce73d1..d6a63ee60bc0 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -521,8 +521,6 @@ do {                                                        
                \
  static inline bool rcu_gp_is_normal(void) { return true; }
  static inline bool rcu_gp_is_expedited(void) { return false; }
  static inline bool rcu_async_should_hurry(void) { return false; }
-static inline void rcu_expedite_gp(void) { }
-static inline void rcu_unexpedite_gp(void) { }
  static inline void rcu_async_hurry(void) { }
  static inline void rcu_async_relax(void) { }
  static inline bool rcu_cpu_online(int cpu) { return true; }
@@ -530,8 +528,6 @@ static inline bool rcu_cpu_online(int cpu) { return true; }
  bool rcu_gp_is_normal(void);     /* Internal RCU use. */
  bool rcu_gp_is_expedited(void);  /* Internal RCU use. */
  bool rcu_async_should_hurry(void);  /* Internal RCU use. */
-void rcu_expedite_gp(void);
-void rcu_unexpedite_gp(void);
  void rcu_async_hurry(void);
  void rcu_async_relax(void);
  void rcupdate_announce_bootup_oddness(void);

Reply via email to