* [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks
2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
@ 2026-10-15 12:43 ` Peng Wang
2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
2 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 12:43 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner
Cc: Peng Wang, Greg Kroah-Hartman, Rafael J . Wysocki,
Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Peter Zijlstra, Waiman Long, Tejun Heo,
He Rongguang, linux-kernel, linux-api, driver-core,
linux-trace-kernel, cgroups
Workloads and their need for periodic ticks can change after boot.
Operators may need to retain the non-idle scheduler tick on selected
CPUs in the boot-time nohz_full set while permitting tick suppression
on others, without changing the isolation configuration.
The policy can be changed without taking CPUs offline.
Add a per-CPU POLICY dependency to inhibit non-idle tick suppression.
All nohz_full CPUs remain permitted by default. Revocation uses the
existing asynchronous kick; granting permission clears only POLICY.
Preserve the policy across hotplug and recognize it in tick_stop tracing.
Idle tick suppression is unchanged.
Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
---
include/linux/tick.h | 8 +++--
include/trace/events/timer.h | 3 +-
kernel/time/tick-sched.c | 62 ++++++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/include/linux/tick.h b/include/linux/tick.h
index b121c5d53e308..08d272dca0947 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -111,9 +111,10 @@ enum tick_dep_bits {
TICK_DEP_BIT_SCHED = 2,
TICK_DEP_BIT_CLOCK_UNSTABLE = 3,
TICK_DEP_BIT_RCU = 4,
- TICK_DEP_BIT_RCU_EXP = 5
+ TICK_DEP_BIT_RCU_EXP = 5,
+ TICK_DEP_BIT_POLICY = 6
};
-#define TICK_DEP_BIT_MAX TICK_DEP_BIT_RCU_EXP
+#define TICK_DEP_BIT_MAX TICK_DEP_BIT_POLICY
#define TICK_DEP_MASK_NONE 0
#define TICK_DEP_MASK_POSIX_TIMER (1 << TICK_DEP_BIT_POSIX_TIMER)
@@ -122,6 +123,7 @@ enum tick_dep_bits {
#define TICK_DEP_MASK_CLOCK_UNSTABLE (1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
#define TICK_DEP_MASK_RCU (1 << TICK_DEP_BIT_RCU)
#define TICK_DEP_MASK_RCU_EXP (1 << TICK_DEP_BIT_RCU_EXP)
+#define TICK_DEP_MASK_POLICY (1 << TICK_DEP_BIT_POLICY)
#ifdef CONFIG_NO_HZ_COMMON
extern bool tick_nohz_enabled;
@@ -205,6 +207,8 @@ extern void tick_nohz_dep_set_signal(struct task_struct *tsk,
extern void tick_nohz_dep_clear_signal(struct signal_struct *signal,
enum tick_dep_bits bit);
extern bool tick_nohz_cpu_hotpluggable(unsigned int cpu);
+extern void tick_nohz_full_get_allowed(struct cpumask *mask);
+extern int tick_nohz_full_set_allowed(const struct cpumask *mask);
/*
* The below are tick_nohz_[set,clear]_dep() wrappers that optimize off-cases
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 3aa0608c63611..dff9579cd90eb 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -435,7 +435,8 @@ TRACE_EVENT(itimer_expire,
tick_dep_name(SCHED) \
tick_dep_name(CLOCK_UNSTABLE) \
tick_dep_name(RCU) \
- tick_dep_name_end(RCU_EXP)
+ tick_dep_name(RCU_EXP) \
+ tick_dep_name_end(POLICY)
#undef tick_dep_name
#undef tick_dep_mask_name
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 6c3fea3867139..d76128cba985c 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -27,6 +27,7 @@
#include <linux/posix-timers.h>
#include <linux/context_tracking.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
#include <asm/irq_regs.h>
@@ -337,6 +338,7 @@ EXPORT_SYMBOL_GPL(tick_nohz_full_mask);
bool tick_nohz_full_running;
EXPORT_SYMBOL_GPL(tick_nohz_full_running);
static atomic_t tick_dep_mask;
+static DEFINE_MUTEX(tick_nohz_full_policy_mutex);
static bool check_tick_dependency(atomic_t *dep)
{
@@ -375,6 +377,11 @@ static bool check_tick_dependency(atomic_t *dep)
return true;
}
+ if (val & TICK_DEP_MASK_POLICY) {
+ trace_tick_stop(0, TICK_DEP_MASK_POLICY);
+ return true;
+ }
+
return false;
}
@@ -556,6 +563,57 @@ void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
}
EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu);
+/* Read policy, not whether a CPU currently has its tick stopped. */
+void tick_nohz_full_get_allowed(struct cpumask *mask)
+{
+ int cpu;
+
+ cpumask_clear(mask);
+ if (!tick_nohz_full_enabled())
+ return;
+
+ /* Exclude the reset of tick_cpu_sched during CPU teardown. */
+ cpus_read_lock();
+ mutex_lock(&tick_nohz_full_policy_mutex);
+ for_each_cpu(cpu, tick_nohz_full_mask) {
+ struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+ if (!(atomic_read(&ts->tick_dep_mask) & TICK_DEP_MASK_POLICY))
+ cpumask_set_cpu(cpu, mask);
+ }
+ mutex_unlock(&tick_nohz_full_policy_mutex);
+ cpus_read_unlock();
+}
+
+int tick_nohz_full_set_allowed(const struct cpumask *mask)
+{
+ int cpu;
+
+ if (!tick_nohz_full_enabled())
+ return -EOPNOTSUPP;
+ if (!cpumask_subset(mask, tick_nohz_full_mask))
+ return -EINVAL;
+
+ cpus_read_lock();
+ mutex_lock(&tick_nohz_full_policy_mutex);
+ for_each_cpu(cpu, tick_nohz_full_mask) {
+ if (cpumask_test_cpu(cpu, mask)) {
+ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_POLICY);
+ } else if (cpu_online(cpu)) {
+ /* The existing kick requests an asynchronous restart. */
+ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_POLICY);
+ } else {
+ struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+ /* Record policy without queuing irq_work on an offline CPU. */
+ atomic_or(TICK_DEP_MASK_POLICY, &ts->tick_dep_mask);
+ }
+ }
+ mutex_unlock(&tick_nohz_full_policy_mutex);
+ cpus_read_unlock();
+ return 0;
+}
+
/*
* Set a per-task tick dependency. RCU needs this. Also posix CPU timers
* in order to elapse per task timers.
@@ -1528,6 +1586,7 @@ void tick_sched_timer_dying(int cpu)
{
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
unsigned long idle_calls, idle_sleeps;
+ int policy;
/* This must happen before hrtimers are migrated! */
if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES))
@@ -1535,7 +1594,10 @@ void tick_sched_timer_dying(int cpu)
idle_calls = ts->idle_calls;
idle_sleeps = ts->idle_sleeps;
+ /* Preserve only the policy dependency across CPU offline/online. */
+ policy = atomic_read(&ts->tick_dep_mask) & TICK_DEP_MASK_POLICY;
memset(ts, 0, sizeof(*ts));
+ atomic_set(&ts->tick_dep_mask, policy);
ts->idle_calls = idle_calls;
ts->idle_sleeps = idle_sleeps;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
@ 2026-10-15 12:43 ` Peng Wang
2026-10-15 16:07 ` Waiman Long
2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
2 siblings, 1 reply; 7+ messages in thread
From: Peng Wang @ 2026-10-15 12:43 UTC (permalink / raw)
To: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner
Cc: Peng Wang, Greg Kroah-Hartman, Rafael J . Wysocki,
Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Peter Zijlstra, Waiman Long, Tejun Heo,
He Rongguang, linux-kernel, linux-api, driver-core,
linux-trace-kernel, cgroups
Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
nohz_full CPUs permitted to suppress their non-idle scheduler tick.
Writes replace the entire list; reads report policy, not current tick
state. Reject invalid input before updating policy. Document asynchronous
revocation, offline CPU configuration and persistence across hotplug.
The existing nohz_full attribute continues to report membership.
Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
---
.../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++
drivers/base/cpu.c | 46 +++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 82d10d556cc89..edf3408fd84c8 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -767,6 +767,46 @@ Description: Preferred MTE tag checking mode
See also: Documentation/arch/arm64/memory-tagging-extension.rst
+What: /sys/devices/system/cpu/nohz_full_allowed
+Date: October 2026
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:
+ (RW) CPUs permitted to stop the scheduler tick while non-idle.
+ Available with CONFIG_NO_HZ_FULL. The default is the complete
+ nohz_full CPU list. Readback reports permission, not the current
+ tick state: all the usual tick dependencies still apply.
+
+ A write replaces the entire list, using CPU-list syntax (for
+ example, "1-3,5"). An empty line revokes permission from all
+ nohz_full CPUs. Invalid input is rejected without changing
+ policy. A parsed list containing CPUs outside nohz_full fails
+ with EINVAL. CPU numbers beyond the mask range and numeric
+ overflows are rejected by the CPU-list parser with ERANGE and
+ EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
+ bytes, otherwise E2BIG is returned. Embedded NULs and newlines
+ other than a trailing newline are rejected with EINVAL. Valid
+ writes without an active nohz_full configuration fail with
+ EOPNOTSUPP.
+
+ Reads fail with EOVERFLOW if the formatted output reaches
+ PAGE_SIZE - 1 bytes, rather than returning a potentially
+ truncated CPU list.
+
+ Revoking permission adds a per-CPU tick dependency. Online CPUs
+ are notified through the existing asynchronous kick mechanism
+ to restart a stopped non-idle tick. A successful write means
+ the policy is updated and any needed notification is queued;
+ it does not wait for tick restart. Changes to multiple CPUs
+ are not simultaneous. Granting permission only removes this
+ dependency and does not force the tick to stop.
+
+ Offline CPUs may be configured without sending notifications.
+ Policy persists across CPU offline/online. Idle tick suppression
+ is unchanged; the policy applies when a CPU leaves idle.
+
+ This interface does not change nohz_full membership, context
+ tracking, RCU offloading, or housekeeping configuration.
+
What: /sys/devices/system/cpu/nohz_full
Date: Apr 2015
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 69e52fed42415..299ce61cef895 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
return sysfs_emit(buf, "\n");
}
static DEVICE_ATTR_RO(nohz_full);
+
+static ssize_t nohz_full_allowed_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ cpumask_var_t mask;
+ ssize_t ret;
+
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ return -ENOMEM;
+
+ tick_nohz_full_get_allowed(mask);
+ ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
+
+ free_cpumask_var(mask);
+
+ /* Never present a truncated CPU list as the complete policy. */
+ return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
+}
+
+static ssize_t nohz_full_allowed_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ cpumask_var_t mask;
+ int ret;
+
+ /* kernfs may truncate an oversized write to PAGE_SIZE. */
+ if (count >= PAGE_SIZE)
+ return -E2BIG;
+ if (memchr(buf, '\0', count) ||
+ (count > 1 && memchr(buf, '\n', count - 1)))
+ return -EINVAL;
+
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ return -ENOMEM;
+
+ ret = cpulist_parse(buf, mask);
+ if (!ret)
+ ret = tick_nohz_full_set_allowed(mask);
+
+ free_cpumask_var(mask);
+
+ return ret ? ret : count;
+}
+static DEVICE_ATTR_RW(nohz_full_allowed);
#endif
#ifdef CONFIG_CRASH_HOTPLUG
@@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
&dev_attr_housekeeping.attr,
#ifdef CONFIG_NO_HZ_FULL
&dev_attr_nohz_full.attr,
+ &dev_attr_nohz_full_allowed.attr,
#endif
#ifdef CONFIG_CRASH_HOTPLUG
&dev_attr_crash_hotplug.attr,
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
@ 2026-10-15 16:07 ` Waiman Long
2026-10-15 17:50 ` Peng Wang
0 siblings, 1 reply; 7+ messages in thread
From: Waiman Long @ 2026-10-15 16:07 UTC (permalink / raw)
To: Peng Wang, Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner
Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Tejun Heo, He Rongguang, linux-kernel, linux-api,
driver-core, linux-trace-kernel, cgroups
On 10/15/26 8:43 AM, Peng Wang wrote:
> Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
> nohz_full CPUs permitted to suppress their non-idle scheduler tick.
>
> Writes replace the entire list; reads report policy, not current tick
> state. Reject invalid input before updating policy. Document asynchronous
> revocation, offline CPU configuration and persistence across hotplug.
> The existing nohz_full attribute continues to report membership.
>
> Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
> Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
> Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
> ---
> .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++
> drivers/base/cpu.c | 46 +++++++++++++++++++
> 2 files changed, 86 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
> index 82d10d556cc89..edf3408fd84c8 100644
> --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
> +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
> @@ -767,6 +767,46 @@ Description: Preferred MTE tag checking mode
>
> See also: Documentation/arch/arm64/memory-tagging-extension.rst
>
> +What: /sys/devices/system/cpu/nohz_full_allowed
I do have a problem with the name of this sysfs file. nohz_full is more
than just the tick. The naming may introduce the wrong impression that
all nohz_full behavior can be controlled. May be a name like
"nohz_tick_allowed" which is much more specific will be better.
Regards,
Longman
> +Date: October 2026
> +Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
> +Description:
> + (RW) CPUs permitted to stop the scheduler tick while non-idle.
> + Available with CONFIG_NO_HZ_FULL. The default is the complete
> + nohz_full CPU list. Readback reports permission, not the current
> + tick state: all the usual tick dependencies still apply.
> +
> + A write replaces the entire list, using CPU-list syntax (for
> + example, "1-3,5"). An empty line revokes permission from all
> + nohz_full CPUs. Invalid input is rejected without changing
> + policy. A parsed list containing CPUs outside nohz_full fails
> + with EINVAL. CPU numbers beyond the mask range and numeric
> + overflows are rejected by the CPU-list parser with ERANGE and
> + EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
> + bytes, otherwise E2BIG is returned. Embedded NULs and newlines
> + other than a trailing newline are rejected with EINVAL. Valid
> + writes without an active nohz_full configuration fail with
> + EOPNOTSUPP.
> +
> + Reads fail with EOVERFLOW if the formatted output reaches
> + PAGE_SIZE - 1 bytes, rather than returning a potentially
> + truncated CPU list.
> +
> + Revoking permission adds a per-CPU tick dependency. Online CPUs
> + are notified through the existing asynchronous kick mechanism
> + to restart a stopped non-idle tick. A successful write means
> + the policy is updated and any needed notification is queued;
> + it does not wait for tick restart. Changes to multiple CPUs
> + are not simultaneous. Granting permission only removes this
> + dependency and does not force the tick to stop.
> +
> + Offline CPUs may be configured without sending notifications.
> + Policy persists across CPU offline/online. Idle tick suppression
> + is unchanged; the policy applies when a CPU leaves idle.
> +
> + This interface does not change nohz_full membership, context
> + tracking, RCU offloading, or housekeeping configuration.
> +
> What: /sys/devices/system/cpu/nohz_full
> Date: Apr 2015
> Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 69e52fed42415..299ce61cef895 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
> return sysfs_emit(buf, "\n");
> }
> static DEVICE_ATTR_RO(nohz_full);
> +
> +static ssize_t nohz_full_allowed_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + cpumask_var_t mask;
> + ssize_t ret;
> +
> + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> + return -ENOMEM;
> +
> + tick_nohz_full_get_allowed(mask);
> + ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
> +
> + free_cpumask_var(mask);
> +
> + /* Never present a truncated CPU list as the complete policy. */
> + return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
> +}
> +
> +static ssize_t nohz_full_allowed_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + cpumask_var_t mask;
> + int ret;
> +
> + /* kernfs may truncate an oversized write to PAGE_SIZE. */
> + if (count >= PAGE_SIZE)
> + return -E2BIG;
> + if (memchr(buf, '\0', count) ||
> + (count > 1 && memchr(buf, '\n', count - 1)))
> + return -EINVAL;
> +
> + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> + return -ENOMEM;
> +
> + ret = cpulist_parse(buf, mask);
> + if (!ret)
> + ret = tick_nohz_full_set_allowed(mask);
> +
> + free_cpumask_var(mask);
> +
> + return ret ? ret : count;
> +}
> +static DEVICE_ATTR_RW(nohz_full_allowed);
> #endif
>
> #ifdef CONFIG_CRASH_HOTPLUG
> @@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
> &dev_attr_housekeeping.attr,
> #ifdef CONFIG_NO_HZ_FULL
> &dev_attr_nohz_full.attr,
> + &dev_attr_nohz_full_allowed.attr,
> #endif
> #ifdef CONFIG_CRASH_HOTPLUG
> &dev_attr_crash_hotplug.attr,
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
2026-10-15 16:07 ` Waiman Long
@ 2026-10-15 17:50 ` Peng Wang
0 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 17:50 UTC (permalink / raw)
To: Waiman Long
Cc: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner, Greg Kroah-Hartman, Rafael J . Wysocki,
Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Peter Zijlstra, Tejun Heo, He Rongguang,
linux-kernel, linux-api, driver-core, linux-trace-kernel, cgroups
On Thu, Oct 15, 2026 at 12:07:14PM -0400, Waiman Long wrote:
>
> On 10/15/26 8:43 AM, Peng Wang wrote:
> > Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
> > nohz_full CPUs permitted to suppress their non-idle scheduler tick.
> >
> > Writes replace the entire list; reads report policy, not current tick
> > state. Reject invalid input before updating policy. Document asynchronous
> > revocation, offline CPU configuration and persistence across hotplug.
> > The existing nohz_full attribute continues to report membership.
> >
> > Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
> > Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
> > Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
> > ---
> > .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++
> > drivers/base/cpu.c | 46 +++++++++++++++++++
> > 2 files changed, 86 insertions(+)
> >
> > diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
> > index 82d10d556cc89..edf3408fd84c8 100644
> > --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
> > +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
> > @@ -767,6 +767,46 @@ Description: Preferred MTE tag checking mode
> > See also: Documentation/arch/arm64/memory-tagging-extension.rst
> > +What: /sys/devices/system/cpu/nohz_full_allowed
>
> I do have a problem with the name of this sysfs file. nohz_full is more than
> just the tick. The naming may introduce the wrong impression that all
> nohz_full behavior can be controlled. May be a name like "nohz_tick_allowed"
> which is much more specific will be better.
Hi Waiman,
Agreed, nohz_tick_allowed describes the scope more accurately.
If the control remains in sysfs, I'll use that name in the next version.
Thanks,
Peng
>
> Regards,
> Longman
>
> > +Date: October 2026
> > +Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
> > +Description:
> > + (RW) CPUs permitted to stop the scheduler tick while non-idle.
> > + Available with CONFIG_NO_HZ_FULL. The default is the complete
> > + nohz_full CPU list. Readback reports permission, not the current
> > + tick state: all the usual tick dependencies still apply.
> > +
> > + A write replaces the entire list, using CPU-list syntax (for
> > + example, "1-3,5"). An empty line revokes permission from all
> > + nohz_full CPUs. Invalid input is rejected without changing
> > + policy. A parsed list containing CPUs outside nohz_full fails
> > + with EINVAL. CPU numbers beyond the mask range and numeric
> > + overflows are rejected by the CPU-list parser with ERANGE and
> > + EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
> > + bytes, otherwise E2BIG is returned. Embedded NULs and newlines
> > + other than a trailing newline are rejected with EINVAL. Valid
> > + writes without an active nohz_full configuration fail with
> > + EOPNOTSUPP.
> > +
> > + Reads fail with EOVERFLOW if the formatted output reaches
> > + PAGE_SIZE - 1 bytes, rather than returning a potentially
> > + truncated CPU list.
> > +
> > + Revoking permission adds a per-CPU tick dependency. Online CPUs
> > + are notified through the existing asynchronous kick mechanism
> > + to restart a stopped non-idle tick. A successful write means
> > + the policy is updated and any needed notification is queued;
> > + it does not wait for tick restart. Changes to multiple CPUs
> > + are not simultaneous. Granting permission only removes this
> > + dependency and does not force the tick to stop.
> > +
> > + Offline CPUs may be configured without sending notifications.
> > + Policy persists across CPU offline/online. Idle tick suppression
> > + is unchanged; the policy applies when a CPU leaves idle.
> > +
> > + This interface does not change nohz_full membership, context
> > + tracking, RCU offloading, or housekeeping configuration.
> > +
> > What: /sys/devices/system/cpu/nohz_full
> > Date: Apr 2015
> > Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
> > diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> > index 69e52fed42415..299ce61cef895 100644
> > --- a/drivers/base/cpu.c
> > +++ b/drivers/base/cpu.c
> > @@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
> > return sysfs_emit(buf, "\n");
> > }
> > static DEVICE_ATTR_RO(nohz_full);
> > +
> > +static ssize_t nohz_full_allowed_show(struct device *dev,
> > + struct device_attribute *attr, char *buf)
> > +{
> > + cpumask_var_t mask;
> > + ssize_t ret;
> > +
> > + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> > + return -ENOMEM;
> > +
> > + tick_nohz_full_get_allowed(mask);
> > + ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
> > +
> > + free_cpumask_var(mask);
> > +
> > + /* Never present a truncated CPU list as the complete policy. */
> > + return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
> > +}
> > +
> > +static ssize_t nohz_full_allowed_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + cpumask_var_t mask;
> > + int ret;
> > +
> > + /* kernfs may truncate an oversized write to PAGE_SIZE. */
> > + if (count >= PAGE_SIZE)
> > + return -E2BIG;
> > + if (memchr(buf, '\0', count) ||
> > + (count > 1 && memchr(buf, '\n', count - 1)))
> > + return -EINVAL;
> > +
> > + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> > + return -ENOMEM;
> > +
> > + ret = cpulist_parse(buf, mask);
> > + if (!ret)
> > + ret = tick_nohz_full_set_allowed(mask);
> > +
> > + free_cpumask_var(mask);
> > +
> > + return ret ? ret : count;
> > +}
> > +static DEVICE_ATTR_RW(nohz_full_allowed);
> > #endif
> > #ifdef CONFIG_CRASH_HOTPLUG
> > @@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
> > &dev_attr_housekeeping.attr,
> > #ifdef CONFIG_NO_HZ_FULL
> > &dev_attr_nohz_full.attr,
> > + &dev_attr_nohz_full_allowed.attr,
> > #endif
> > #ifdef CONFIG_CRASH_HOTPLUG
> > &dev_attr_crash_hotplug.attr,
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression
2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
@ 2026-10-15 16:00 ` Waiman Long
2026-10-15 17:48 ` Peng Wang
2 siblings, 1 reply; 7+ messages in thread
From: Waiman Long @ 2026-10-15 16:00 UTC (permalink / raw)
To: Peng Wang, Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner
Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Tejun Heo, He Rongguang, linux-kernel, linux-api,
driver-core, linux-trace-kernel, cgroups
On 10/15/26 8:43 AM, Peng Wang wrote:
> Workloads and their need for periodic ticks can change after boot.
> This series lets userspace choose at runtime which CPUs in the boot-time
> nohz_full set retain the non-idle scheduler tick and which are permitted
> to stop it, while preserving the existing isolation configuration.
>
> The first patch adds a per-CPU tick dependency; the second exposes a
> sysfs CPU list. Permission defaults to all nohz_full CPUs. Revocation
> uses the existing asynchronous kick. Idle tick suppression is unchanged,
> and policy persists across hotplug.
So you are basically setting up more nohz_full CPUs than the system
actually needs to use at the moment and so want to disable nohz/tick
part of nohz_full CPUs that don't need it. Can you elaborate more about
the problems solve by introducing this new behavior?
>
> Existing cpuset partition modes do not express this independent tick
> policy. Feedback on the proposed interface is welcome.
We are planning to eventually extend cpuset partition mode to change
nohz_full at runtime. This is still a work in progress.
Regards,
Longman
>
> Thanks,
> Peng
>
> Peng Wang (2):
> tick/nohz: Add a policy dependency for full dynticks
> cpu: Add sysfs control of full dynticks policy
>
> .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++
> drivers/base/cpu.c | 46 ++++++++++++++
> include/linux/tick.h | 8 ++-
> include/trace/events/timer.h | 3 +-
> kernel/time/tick-sched.c | 62 +++++++++++++++++++
> 5 files changed, 156 insertions(+), 3 deletions(-)
>
>
> base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression
2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
@ 2026-10-15 17:48 ` Peng Wang
0 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 17:48 UTC (permalink / raw)
To: Waiman Long
Cc: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
Thomas Gleixner, Greg Kroah-Hartman, Rafael J . Wysocki,
Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Peter Zijlstra, Tejun Heo, He Rongguang,
linux-kernel, linux-api, driver-core, linux-trace-kernel, cgroups
On Thu, Oct 15, 2026 at 12:00:25PM -0400, Waiman Long wrote:
> On 10/15/26 8:43 AM, Peng Wang wrote:
> > Workloads and their need for periodic ticks can change after boot.
> > This series lets userspace choose at runtime which CPUs in the boot-time
> > nohz_full set retain the non-idle scheduler tick and which are permitted
> > to stop it, while preserving the existing isolation configuration.
> >
> > The first patch adds a per-CPU tick dependency; the second exposes a
> > sysfs CPU list. Permission defaults to all nohz_full CPUs. Revocation
> > uses the existing asynchronous kick. Idle tick suppression is unchanged,
> > and policy persists across hotplug.
> So you are basically setting up more nohz_full CPUs than the system actually
> needs to use at the moment and so want to disable nohz/tick part of
> nohz_full CPUs that don't need it. Can you elaborate more about the problems
> solve by introducing this new behavior?
Hi Waiman,
Yes. We have CPU-pinned workloads that benefit from reduced periodic
tick interference. The desired tick policy changes with CPU allocation.
With spare capacity, we allow selected nohz_full CPUs to stop their
tick. When capacity is fully allocated, we prefer to retain the
non-idle periodic tick across CPUs, avoiding an additional difference
in tick interference between housekeeping and nohz_full CPUs.
A CPU may still have only one runnable task in either case, so the
existing tick dependencies do not express this policy.
This series keeps the boot-time nohz_full CPU set, context tracking,
RCU offloading and housekeeping configuration unchanged. It only
controls whether those CPUs may stop their non-idle tick. The policy
can be changed without taking CPUs offline.
> >
> > Existing cpuset partition modes do not express this independent tick
> > policy. Feedback on the proposed interface is welcome.
>
> We are planning to eventually extend cpuset partition mode to change
> nohz_full at runtime. This is still a work in progress.
Thanks for mentioning the cpuset work. Would this tick-only policy
fit into that plan? The core mechanism in patch 1 is independent of
the sysfs interface.
Thanks,
Peng
>
> Regards,
> Longman
>
> >
> > Thanks,
> > Peng
> >
> > Peng Wang (2):
> > tick/nohz: Add a policy dependency for full dynticks
> > cpu: Add sysfs control of full dynticks policy
> >
> > .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++
> > drivers/base/cpu.c | 46 ++++++++++++++
> > include/linux/tick.h | 8 ++-
> > include/trace/events/timer.h | 3 +-
> > kernel/time/tick-sched.c | 62 +++++++++++++++++++
> > 5 files changed, 156 insertions(+), 3 deletions(-)
> >
> >
> > base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
>
^ permalink raw reply [flat|nested] 7+ messages in thread