Skip to content

Commit e59e10f

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched: Add /debug/sched_preempt
Add a debugfs file to muck about with the preempt mode at runtime. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lkml.kernel.org/r/YAsGiUYf6NyaTplX@hirez.programming.kicks-ass.net
1 parent 826bfeb commit e59e10f

File tree

1 file changed

+126
-9
lines changed

1 file changed

+126
-9
lines changed

kernel/sched/core.c

Lines changed: 126 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5363,37 +5363,154 @@ EXPORT_STATIC_CALL(preempt_schedule_notrace);
53635363
* preempt_schedule_notrace <- preempt_schedule_notrace
53645364
* irqentry_exit_cond_resched <- irqentry_exit_cond_resched
53655365
*/
5366-
static int __init setup_preempt_mode(char *str)
5366+
5367+
enum {
5368+
preempt_dynamic_none = 0,
5369+
preempt_dynamic_voluntary,
5370+
preempt_dynamic_full,
5371+
};
5372+
5373+
static int preempt_dynamic_mode = preempt_dynamic_full;
5374+
5375+
static int sched_dynamic_mode(const char *str)
53675376
{
5368-
if (!strcmp(str, "none")) {
5377+
if (!strcmp(str, "none"))
5378+
return 0;
5379+
5380+
if (!strcmp(str, "voluntary"))
5381+
return 1;
5382+
5383+
if (!strcmp(str, "full"))
5384+
return 2;
5385+
5386+
return -1;
5387+
}
5388+
5389+
static void sched_dynamic_update(int mode)
5390+
{
5391+
/*
5392+
* Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
5393+
* the ZERO state, which is invalid.
5394+
*/
5395+
static_call_update(cond_resched, __cond_resched);
5396+
static_call_update(might_resched, __cond_resched);
5397+
static_call_update(preempt_schedule, __preempt_schedule_func);
5398+
static_call_update(preempt_schedule_notrace, __preempt_schedule_notrace_func);
5399+
static_call_update(irqentry_exit_cond_resched, irqentry_exit_cond_resched);
5400+
5401+
switch (mode) {
5402+
case preempt_dynamic_none:
53695403
static_call_update(cond_resched, __cond_resched);
53705404
static_call_update(might_resched, (typeof(&__cond_resched)) __static_call_return0);
53715405
static_call_update(preempt_schedule, (typeof(&preempt_schedule)) NULL);
53725406
static_call_update(preempt_schedule_notrace, (typeof(&preempt_schedule_notrace)) NULL);
53735407
static_call_update(irqentry_exit_cond_resched, (typeof(&irqentry_exit_cond_resched)) NULL);
5374-
pr_info("Dynamic Preempt: %s\n", str);
5375-
} else if (!strcmp(str, "voluntary")) {
5408+
pr_info("Dynamic Preempt: none\n");
5409+
break;
5410+
5411+
case preempt_dynamic_voluntary:
53765412
static_call_update(cond_resched, __cond_resched);
53775413
static_call_update(might_resched, __cond_resched);
53785414
static_call_update(preempt_schedule, (typeof(&preempt_schedule)) NULL);
53795415
static_call_update(preempt_schedule_notrace, (typeof(&preempt_schedule_notrace)) NULL);
53805416
static_call_update(irqentry_exit_cond_resched, (typeof(&irqentry_exit_cond_resched)) NULL);
5381-
pr_info("Dynamic Preempt: %s\n", str);
5382-
} else if (!strcmp(str, "full")) {
5417+
pr_info("Dynamic Preempt: voluntary\n");
5418+
break;
5419+
5420+
case preempt_dynamic_full:
53835421
static_call_update(cond_resched, (typeof(&__cond_resched)) __static_call_return0);
53845422
static_call_update(might_resched, (typeof(&__cond_resched)) __static_call_return0);
53855423
static_call_update(preempt_schedule, __preempt_schedule_func);
53865424
static_call_update(preempt_schedule_notrace, __preempt_schedule_notrace_func);
53875425
static_call_update(irqentry_exit_cond_resched, irqentry_exit_cond_resched);
5388-
pr_info("Dynamic Preempt: %s\n", str);
5389-
} else {
5390-
pr_warn("Dynamic Preempt: Unsupported preempt mode %s, default to full\n", str);
5426+
pr_info("Dynamic Preempt: full\n");
5427+
break;
5428+
}
5429+
5430+
preempt_dynamic_mode = mode;
5431+
}
5432+
5433+
static int __init setup_preempt_mode(char *str)
5434+
{
5435+
int mode = sched_dynamic_mode(str);
5436+
if (mode < 0) {
5437+
pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
53915438
return 1;
53925439
}
5440+
5441+
sched_dynamic_update(mode);
53935442
return 0;
53945443
}
53955444
__setup("preempt=", setup_preempt_mode);
53965445

5446+
#ifdef CONFIG_SCHED_DEBUG
5447+
5448+
static ssize_t sched_dynamic_write(struct file *filp, const char __user *ubuf,
5449+
size_t cnt, loff_t *ppos)
5450+
{
5451+
char buf[16];
5452+
int mode;
5453+
5454+
if (cnt > 15)
5455+
cnt = 15;
5456+
5457+
if (copy_from_user(&buf, ubuf, cnt))
5458+
return -EFAULT;
5459+
5460+
buf[cnt] = 0;
5461+
mode = sched_dynamic_mode(strstrip(buf));
5462+
if (mode < 0)
5463+
return mode;
5464+
5465+
sched_dynamic_update(mode);
5466+
5467+
*ppos += cnt;
5468+
5469+
return cnt;
5470+
}
5471+
5472+
static int sched_dynamic_show(struct seq_file *m, void *v)
5473+
{
5474+
static const char * preempt_modes[] = {
5475+
"none", "voluntary", "full"
5476+
};
5477+
int i;
5478+
5479+
for (i = 0; i < ARRAY_SIZE(preempt_modes); i++) {
5480+
if (preempt_dynamic_mode == i)
5481+
seq_puts(m, "(");
5482+
seq_puts(m, preempt_modes[i]);
5483+
if (preempt_dynamic_mode == i)
5484+
seq_puts(m, ")");
5485+
5486+
seq_puts(m, " ");
5487+
}
5488+
5489+
seq_puts(m, "\n");
5490+
return 0;
5491+
}
5492+
5493+
static int sched_dynamic_open(struct inode *inode, struct file *filp)
5494+
{
5495+
return single_open(filp, sched_dynamic_show, NULL);
5496+
}
5497+
5498+
static const struct file_operations sched_dynamic_fops = {
5499+
.open = sched_dynamic_open,
5500+
.write = sched_dynamic_write,
5501+
.read = seq_read,
5502+
.llseek = seq_lseek,
5503+
.release = single_release,
5504+
};
5505+
5506+
static __init int sched_init_debug_dynamic(void)
5507+
{
5508+
debugfs_create_file("sched_preempt", 0644, NULL, NULL, &sched_dynamic_fops);
5509+
return 0;
5510+
}
5511+
late_initcall(sched_init_debug_dynamic);
5512+
5513+
#endif /* CONFIG_SCHED_DEBUG */
53975514
#endif /* CONFIG_PREEMPT_DYNAMIC */
53985515

53995516

0 commit comments

Comments
 (0)