tick/nohz: Add runtime control of non-idle tick suppression
Subsystems (6)
cover tick/nohz: Add runtime control of non-idle tick suppression
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.
Existing cpuset partition modes do not express this independent tick policy. Feedback on the proposed interface is welcome.
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
RFC PATCH 1/2 tick/nohz: Add a policy dependency for full dynticks
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.
--- include/linux/tick.h | 8 +++-- include/trace/events/timer.h | 3 +- kernel/time/tick-sched.c | 62 ++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-)
include/linux/tick.h +6 -2
@@ -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
include/trace/events/timer.h +2 -1
@@ -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
kernel/time/tick-sched.c +62 -0
99 lines not on this page · raw message
RFC PATCH 2/2 cpu: Add sysfs control of full dynticks policy
In reply to Peng WangExpose 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.
--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)
Documentation/ABI/testing/sysfs-devices-system-cpu +40 -0
@@ -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 <[email protected]> +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 <[email protected]>
drivers/base/cpu.c +46 -0
58 lines not on this page · raw message
Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
Quoted 21 lines · Peng Wang
Expose
nohz_full_allowedunder/sys/devices/system/cpu/as the subset ofnohz_fullCPUs 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_fullattribute continues to report membership.Co-developed-by He Rongguang <[email protected]>Signed-off-by He Rongguang <[email protected]>Signed-off-by Peng Wang <[email protected]>--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)Documentation/ABI/testing/sysfs-devices-system-cpu +0
-0
Documentation/ABI/testing/sysfs-devices-system-cpu Description: Preferred MTE tag checking mode · line 770
Quoted 4 lines
Documentation/ABI/testing/sysfs-devices-system-cpu +1
-0@@ -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
Quoted 106 lines
Documentation/ABI/testing/sysfs-devices-system-cpu +39
-0+Date: October 2026 +Contact: Linux kernel mailing list <[email protected]> +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 <[email protected]>drivers/base/cpu.c +46
-0@@ -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,
Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
Quoted 18 lines · Waiman Long
Quoted 16 lines · Peng Wang
Expose
nohz_full_allowedunder/sys/devices/system/cpu/as the subset ofnohz_fullCPUs 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_fullattribute continues to report membership.Co-developed-by He Rongguang <[email protected]>Signed-off-by He Rongguang <[email protected]>Signed-off-by Peng Wang <[email protected]>--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)
Quoted 12 lines
Documentation/ABI/testing/sysfs-devices-system-cpu Description: Preferred MTE tag checking mode · line 768
Quoted 7 lines
Documentation/ABI/testing/sysfs-devices-system-cpu +1
-0@@ -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_allowedI do have a problem with the name of this sysfs file.
nohz_fullis more than just the tick. The naming may introduce the wrong impression that allnohz_fullbehavior 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
Quoted 110 lines
Regards,
LongmanQuoted 105 lines
Documentation/ABI/testing/sysfs-devices-system-cpu +39
-0+Date: October 2026 +Contact: Linux kernel mailing list <[email protected]> +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 <[email protected]>drivers/base/cpu.c +46
-0@@ -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,
Greg Kroah-Hartman
maintainerRe: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
In reply to Peng WangQuoted 82 lines · Peng Wang
Expose
nohz_full_allowedunder/sys/devices/system/cpu/as the subset ofnohz_fullCPUs 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_fullattribute continues to report membership.Co-developed-by He Rongguang <[email protected]>Signed-off-by He Rongguang <[email protected]>Signed-off-by Peng Wang <[email protected]>--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)Documentation/ABI/testing/sysfs-devices-system-cpu +40
-0@@ -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 <[email protected]> +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 <[email protected]>drivers/base/cpu.c +7
-0@@ -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; +
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 343
Quoted 10 lines
drivers/base/cpu.c +10
-0+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;
Why not? What will userspace do then if it gets -EOVERFLOW as it can not get the full list?
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 355
Quoted 12 lines
drivers/base/cpu.c +12
-0+} + +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 ;
How are you getting a larger than PAGE_SIZE value here?
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 358
Quoted 3 lines
drivers/base/cpu.c +3
-0+if (memchr (buf,'\0' , count) || + (count >1 &&memchr (buf,'\n' , count -1 ))) +return -EINVAL ;
What are you testing for here, sorry, I can't easily figure it out.
thanks,
greg k-h
Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
Quoted 88 lines · Greg Kroah-Hartman
Quoted 87 lines · Peng Wang
Expose
nohz_full_allowedunder/sys/devices/system/cpu/as the subset ofnohz_fullCPUs 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_fullattribute continues to report membership.Co-developed-by He Rongguang <[email protected]>Signed-off-by He Rongguang <[email protected]>Signed-off-by Peng Wang <[email protected]>--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)Documentation/ABI/testing/sysfs-devices-system-cpu +40
-0@@ -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 <[email protected]> +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 <[email protected]>drivers/base/cpu.c +12
-0@@ -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));
Quoted 8 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 343
Quoted 5 lines
drivers/base/cpu.c +5
-0+ +free_cpumask_var (mask); + +/* Never present a truncated CPU list as the complete policy. */ +return ret ==PAGE_SIZE -1 ? -EOVERFLOW : ret;Why not? What will userspace do then if it gets
-EOVERFLOWas it can not get the full list?
Hi Greg,
There is no way to retrieve the full list through this attribute. The intent was to avoid returning a truncated list that userspace could write back, unintentionally revoking permission for the omitted CPUs. Returning an error does not solve that interface limitation.
Quoted 15 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 355
Quoted 13 lines
drivers/base/cpu.c +12
-0+} + +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 ;How are you getting a larger than
PAGE_SIZEvalue here?
I cannot; kernfs caps count at PAGE_SIZE. The check is intended for count == PAGE_SIZE, to avoid applying a potentially truncated prefix as a complete list. It also rejects an exactly page-sized input.
Quoted 6 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 358
Quoted 4 lines
drivers/base/cpu.c +3
-0+if (memchr (buf,'\0' , count) || + (count >1 &&memchr (buf,'\n' , count -1 ))) +return -EINVAL ;What are you testing for here, sorry, I can't easily figure it out.
The checks reject user-supplied NULs and non-final newlines. For example, cpulist_parse() accepts "1\n2\n" as CPU 1 only, while store() would report the full input as consumed. The NUL appended by kernfs is at buf[count], outside the checked range.
I propose replacing the global attribute with /sys/devices/system/cpu/cpuN/nohz_tick_allowed, available only on nohz_full CPUs. Writing 0 would prevent non-idle tick suppression, using the existing asynchronous kick when needed. Writing 1 would allow suppression, subject to the existing tick dependencies. Readback would report policy, not the current tick state.
Each write would affect only that CPU, without changing nohz_full membership or other isolation settings. This would give up the single-write whole-list replacement. Would that be a better fit?
Thanks,
Peng
Quoted 4 lines
thanks,
greg k-h
Greg Kroah-Hartman
maintainerRe: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
Quoted 98 lines · Peng Wang
Quoted 88 lines · Greg Kroah-Hartman
Quoted 87 lines · Peng Wang
Expose
nohz_full_allowedunder/sys/devices/system/cpu/as the subset ofnohz_fullCPUs 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_fullattribute continues to report membership.Co-developed-by He Rongguang <[email protected]>Signed-off-by He Rongguang <[email protected]>Signed-off-by Peng Wang <[email protected]>--- .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++ drivers/base/cpu.c | 46 +++++++++++++++++++ 2 files changed, 86 insertions(+)Documentation/ABI/testing/sysfs-devices-system-cpu +40
-0@@ -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 <[email protected]> +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 <[email protected]>drivers/base/cpu.c +12
-0@@ -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));Quoted 8 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 343
Quoted 5 lines
drivers/base/cpu.c +5
-0+ +free_cpumask_var (mask); + +/* Never present a truncated CPU list as the complete policy. */ +return ret ==PAGE_SIZE -1 ? -EOVERFLOW : ret;Why not? What will userspace do then if it gets
-EOVERFLOWas it can not get the full list?
Quoted 6 lines
Hi Greg,
There is no way to retrieve the full list through this attribute. The intent was to avoid returning a truncated list that userspace could write back, unintentionally revoking permission for the omitted CPUs. Returning an error does not solve that interface limitation.
If you _MUST_ have such a size of a sysfs file, then use a binary attribute which can accept any size. I think we have had to do that for other sysfs files that show this information in the past, right? Please check them.
Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
drivers/base/cpu.c +6
-0+} + +static ssize_t nohz_full_allowed_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{Quoted 8 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 355
Quoted 6 lines
drivers/base/cpu.c +6
-0+cpumask_var_t mask; +int ret; + +/* kernfs may truncate an oversized write to PAGE_SIZE. */ +if (count >=PAGE_SIZE ) +return -E2BIG ;How are you getting a larger than
PAGE_SIZEvalue here?
Quoted 3 lines
I cannot; kernfs caps count at
PAGE_SIZE. The check is intended for count ==PAGE_SIZE, to avoid applying a potentially truncated prefix as a complete list. It also rejects an exactly page-sized input.
If the check is for == PAGE_SIZE then check for that, not for something that can never happen :)
But again, don't do this at all by using a binary attribute if you are going to be needing to accept larger amounts of data. Don't create a known-broken api from the start please.
Quoted 11 lines
Quoted 6 lines
drivers/base/cpu.c static ssize_t nohz_full_show(struct device *dev, · line 358
Quoted 4 lines
drivers/base/cpu.c +3
-0+if (memchr (buf,'\0' , count) || + (count >1 &&memchr (buf,'\n' , count -1 ))) +return -EINVAL ;What are you testing for here, sorry, I can't easily figure it out.
The checks reject user-supplied NULs and non-final newlines. For example,
cpulist_parse()accepts "1\n2\n" as CPU 1 only, whilestore()would report the full input as consumed. The NUL appended by kernfs is at buf[count], outside the checked range.
Please document that in a comment here.
Quoted 10 lines
I propose replacing the global attribute with
/sys/devices/system/cpu/cpuN/nohz_tick_allowed, available only onnohz_fullCPUs. Writing 0 would prevent non-idle tick suppression, using the existing asynchronous kick when needed. Writing 1 would allow suppression, subject to the existing tick dependencies. Readback would report policy, not the current tick state.Each write would affect only that CPU, without changing
nohz_fullmembership or other isolation settings. This would give up the single-write whole-list replacement. Would that be a better fit?
That's much simpler, so I'm all for that from a sysfs point of view, thanks.
greg k-h
Quoted 9 lines · Peng Wang
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_fullset 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_fullCPUs. 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?
Quoted 3 lines
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
Quoted 17 lines
Thanks,
PengPeng 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
Quoted 6 lines · Waiman Long
Quoted 5 lines · Peng Wang
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_fullset retain the non-idle scheduler tick and which are permitted to stop it, while preserving the existing isolation configuration.
Quoted 8 lines
Quoted 4 lines
The first patch adds a per-CPU tick dependency; the second exposes a sysfs CPU list. Permission defaults to all
nohz_fullCPUs. Revocation uses the existing asynchronous kick. Idle tick suppression is unchanged, and policy persists across hotplug.So you are basically setting up more
nohz_fullCPUs than the system actually needs to use at the moment and so want to disable nohz/tick part ofnohz_fullCPUs 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.
Quoted 6 lines
Quoted 3 lines
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_fullat 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
Quoted 22 lines
Regards,
LongmanQuoted 17 lines
Thanks,
PengPeng 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
Quoted 17 lines · Peng Wang
Quoted 6 lines · Waiman Long
Quoted 5 lines · Peng Wang
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_fullset retain the non-idle scheduler tick and which are permitted to stop it, while preserving the existing isolation configuration.Quoted 8 lines
Quoted 4 lines
The first patch adds a per-CPU tick dependency; the second exposes a sysfs CPU list. Permission defaults to all
nohz_fullCPUs. Revocation uses the existing asynchronous kick. Idle tick suppression is unchanged, and policy persists across hotplug.So you are basically setting up more
nohz_fullCPUs than the system actually needs to use at the moment and so want to disable nohz/tick part ofnohz_fullCPUs that don't need it. Can you elaborate more about the problems solve by introducing this new behavior?Hi Waiman,
Quoted 7 lines
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_fullCPUs 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 andnohz_fullCPUs.
What problem does that cause?
Quoted 7 lines
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_fullCPU 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.
So the policy is to make the tick keeps running when there is only one running task. Right? I am just not clear about the advantage of doing that. Is there a use case that will require this particular feature? I doubt this will get accepted unless there is a compelling reason to show why we will want to have this feature.
Cheers,
Longman
Quoted 18 lines · Waiman Long
Quoted 17 lines · Peng Wang
Quoted 6 lines · Waiman Long
Quoted 5 lines · Peng Wang
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_fullset retain the non-idle scheduler tick and which are permitted to stop it, while preserving the existing isolation configuration.Quoted 8 lines
Quoted 4 lines
The first patch adds a per-CPU tick dependency; the second exposes a sysfs CPU list. Permission defaults to all
nohz_fullCPUs. Revocation uses the existing asynchronous kick. Idle tick suppression is unchanged, and policy persists across hotplug.So you are basically setting up more
nohz_fullCPUs than the system actually needs to use at the moment and so want to disable nohz/tick part ofnohz_fullCPUs that don't need it. Can you elaborate more about the problems solve by introducing this new behavior?Hi Waiman,
Quoted 8 lines
Quoted 7 lines
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_fullCPUs 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 andnohz_fullCPUs.What problem does that cause?
Hi Waiman,
The concern is placement-dependent performance variation between vCPUs sold under the same specification. Customers do not see which host CPU backs their vCPU, so such differences would appear as unexplained variation within the same specification.
At full allocation, we want a consistent non-idle tick policy across the allocated CPUs to avoid this additional source of variation.
Quoted 8 lines
Quoted 7 lines
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_fullCPU 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.
Quoted 5 lines
So the policy is to make the tick keeps running when there is only one running task. Right? I am just not clear about the advantage of doing that. Is there a use case that will require this particular feature? I doubt this will get accepted unless there is a compelling reason to show why we will want to have this feature.
Yes. We run cloud hosts with vCPU threads pinned one-to-one to host CPUs. Some CPUs are kept outside nohz_full for housekeeping, but they also provide vCPU capacity at full allocation. Dedicating them exclusively to housekeeping would reduce the capacity available to guests.
At full allocation, vCPUs also run on housekeeping CPUs, which retain their non-idle tick. Allowing only the nohz_full CPUs to stop the tick would introduce a placement-dependent difference in tick behavior between vCPUs of the same specification.
We therefore want to restore the non-idle tick on those nohz_full CPUs, accepting the extra tick overhead to remove this controllable difference. Host-side background activity is limited in this deployment, and we can tolerate the remaining housekeeping noise.
With spare capacity, we want to allow selected nohz_full CPUs to stop the tick to reduce host scheduler-tick interference with guest execution. This is an opportunistic optimization when capacity permits.
Host allocation changes as customers acquire or release vCPUs, while other customers' VMs continue running.
A nohz_full CPU hosting a remaining vCPU may still have that vCPU thread as its only runnable task, whether the host is fully or partially allocated. The existing tick dependencies therefore do not express the desired change in policy.
The proposed control allows per-CPU runtime changes without taking CPUs offline or changing the boot-time nohz_full set or other isolation settings.
Thanks,
Peng
Quoted 4 lines
Cheers,
Longman