rseq: Move slice_ext_nsec to debugfs

Move changing the slice ext duration to debugfs, a sliglty less permanent
interface.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143207.923520192@infradead.org
This commit is contained in:
Peter Zijlstra
2026-01-21 14:21:51 +01:00
parent d6200245c7
commit e1d7f54900
3 changed files with 49 additions and 35 deletions

View File

@@ -1248,17 +1248,6 @@ reboot-cmd (SPARC only)
ROM/Flash boot loader. Maybe to tell it what to do after
rebooting. ???
rseq_slice_extension_nsec
=========================
A task can request to delay its scheduling if it is in a critical section
via the prctl(PR_RSEQ_SLICE_EXTENSION_SET) mechanism. This sets the maximum
allowed extension in nanoseconds before scheduling of the task is enforced.
Default value is 10000ns (10us). The possible range is 10000ns (10us) to
50000ns (50us).
This value has a direct correlation to the worst case scheduling latency;
increment at your own risk.
sched_energy_aware
==================

View File

@@ -79,7 +79,9 @@ slice extension by setting rseq::slice_ctrl::request to 1. If the thread is
interrupted and the interrupt results in a reschedule request in the
kernel, then the kernel can grant a time slice extension and return to
userspace instead of scheduling out. The length of the extension is
determined by the ``rseq_slice_extension_nsec`` sysctl.
determined by debugfs:rseq/slice_ext_nsec. The default value is 10 usec; which
is the minimum value. It can be incremented to 50 usecs, however doing so
can/will affect the minimum scheduling latency.
The kernel indicates the grant by clearing rseq::slice_ctrl::request and
setting rseq::slice_ctrl::granted to 1. If there is a reschedule of the

View File

@@ -123,7 +123,6 @@ void __rseq_trace_ip_fixup(unsigned long ip, unsigned long start_ip,
}
#endif /* CONFIG_TRACEPOINTS */
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_RSEQ_STATS
DEFINE_PER_CPU(struct rseq_stats, rseq_stats);
@@ -222,16 +221,19 @@ static const struct file_operations debug_ops = {
.release = single_release,
};
static void rseq_slice_ext_init(struct dentry *root_dir);
static int __init rseq_debugfs_init(void)
{
struct dentry *root_dir = debugfs_create_dir("rseq", NULL);
debugfs_create_file("debug", 0644, root_dir, NULL, &debug_ops);
rseq_stats_init(root_dir);
if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION))
rseq_slice_ext_init(root_dir);
return 0;
}
__initcall(rseq_debugfs_init);
#endif /* CONFIG_DEBUG_FS */
static bool rseq_set_ids(struct task_struct *t, struct rseq_ids *ids, u32 node_id)
{
@@ -515,7 +517,9 @@ struct slice_timer {
void *cookie;
};
unsigned int rseq_slice_ext_nsecs __read_mostly = 10 * NSEC_PER_USEC;
static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
unsigned int rseq_slice_ext_nsecs __read_mostly = rseq_slice_ext_nsecs_min;
static DEFINE_PER_CPU(struct slice_timer, slice_timer);
DEFINE_STATIC_KEY_TRUE(rseq_slice_extension_key);
@@ -761,30 +765,48 @@ SYSCALL_DEFINE0(rseq_slice_yield)
return yielded;
}
#ifdef CONFIG_SYSCTL
static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
static int rseq_slice_ext_show(struct seq_file *m, void *p)
{
seq_printf(m, "%d\n", rseq_slice_ext_nsecs);
return 0;
}
static const struct ctl_table rseq_slice_ext_sysctl[] = {
{
.procname = "rseq_slice_extension_nsec",
.data = &rseq_slice_ext_nsecs,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_douintvec_minmax,
.extra1 = (unsigned int *)&rseq_slice_ext_nsecs_min,
.extra2 = (unsigned int *)&rseq_slice_ext_nsecs_max,
},
static ssize_t rseq_slice_ext_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
unsigned int nsecs;
if (kstrtouint_from_user(ubuf, count, 10, &nsecs))
return -EINVAL;
if (nsecs < rseq_slice_ext_nsecs_min)
return -ERANGE;
if (nsecs > rseq_slice_ext_nsecs_max)
return -ERANGE;
rseq_slice_ext_nsecs = nsecs;
return count;
}
static int rseq_slice_ext_open(struct inode *inode, struct file *file)
{
return single_open(file, rseq_slice_ext_show, inode->i_private);
}
static const struct file_operations slice_ext_ops = {
.open = rseq_slice_ext_open,
.read = seq_read,
.write = rseq_slice_ext_write,
.llseek = seq_lseek,
.release = single_release,
};
static void rseq_slice_sysctl_init(void)
static void rseq_slice_ext_init(struct dentry *root_dir)
{
if (rseq_slice_extension_enabled())
register_sysctl_init("kernel", rseq_slice_ext_sysctl);
debugfs_create_file("slice_ext_nsec", 0644, root_dir, NULL, &slice_ext_ops);
}
#else /* CONFIG_SYSCTL */
static inline void rseq_slice_sysctl_init(void) { }
#endif /* !CONFIG_SYSCTL */
static int __init rseq_slice_cmdline(char *str)
{
@@ -807,8 +829,9 @@ static int __init rseq_slice_init(void)
hrtimer_setup(per_cpu_ptr(&slice_timer.timer, cpu), rseq_slice_expired,
CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED_HARD);
}
rseq_slice_sysctl_init();
return 0;
}
device_initcall(rseq_slice_init);
#else
static void rseq_slice_ext_init(struct dentry *root_dir) { }
#endif /* CONFIG_RSEQ_SLICE_EXTENSION */