Skip to content

Commit 8bdc5da

Browse files
Sebastian Andrzej SiewiorPeter Zijlstra
authored andcommitted
sched: Add a generic function to return the preemption string
The individual architectures often add the preemption model to the begin of the backtrace. This is the case on X86 or ARM64 for the "die" case but not for regular warning. With the addition of DYNAMIC_PREEMPT for PREEMPT_RT we end up with CONFIG_PREEMPT and CONFIG_PREEMPT_RT set simultaneously. That means that everyone who tried to add that piece of information gets it wrong for PREEMPT_RT because PREEMPT is checked first. Provide a generic function which returns the current scheduling model considering LAZY preempt and the current state of PREEMPT_DYNAMIC. The resulting strings are: ┏━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓ ┃ Model ┃ -RT -DYN ┃ +RT -DYN ┃ -RT +DYN ┃ +RT +DYN ┃ ┡━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩ │NONE │ NONE │ n/a │ PREEMPT(none) │ n/a │ ├───────────┼──────────────┼───────────────────┼────────────────────┼───────────────────┤ │VOLUNTARY │ VOLUNTARY │ n/a │ PREEMPT(voluntary) │ n/a │ ├───────────┼──────────────┼───────────────────┼────────────────────┼───────────────────┤ │FULL │ PREEMPT │ PREEMPT_RT │ PREEMPT(full) │ PREEMPT_{RT,full} │ ├───────────┼──────────────┼───────────────────┼────────────────────┼───────────────────┤ │LAZY │ PREEMPT_LAZY │ PREEMPT_{RT,LAZY} │ PREEMPT(lazy) │ PREEMPT_{RT,lazy} │ └───────────┴──────────────┴───────────────────┴────────────────────┴───────────────────┘ [ The dynamic building of the string can lead to an empty string if the function is invoked simultaneously on two CPUs. ] Co-developed-by: "Peter Zijlstra (Intel)" <[email protected]> Signed-off-by: "Peter Zijlstra (Intel)" <[email protected]> Co-developed-by: "Steven Rostedt (Google)" <[email protected]> Signed-off-by: "Steven Rostedt (Google)" <[email protected]> Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Shrikanth Hegde <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4bc4582 commit 8bdc5da

File tree

4 files changed

+56
-4
lines changed

4 files changed

+56
-4
lines changed

include/linux/preempt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ static inline bool preempt_model_rt(void)
515515
return IS_ENABLED(CONFIG_PREEMPT_RT);
516516
}
517517

518+
extern const char *preempt_model_str(void);
519+
518520
/*
519521
* Does the preemption model allow non-cooperative preemption?
520522
*

kernel/sched/core.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7646,10 +7646,57 @@ PREEMPT_MODEL_ACCESSOR(lazy);
76467646

76477647
#else /* !CONFIG_PREEMPT_DYNAMIC: */
76487648

7649+
#define preempt_dynamic_mode -1
7650+
76497651
static inline void preempt_dynamic_init(void) { }
76507652

76517653
#endif /* CONFIG_PREEMPT_DYNAMIC */
76527654

7655+
const char *preempt_modes[] = {
7656+
"none", "voluntary", "full", "lazy", NULL,
7657+
};
7658+
7659+
const char *preempt_model_str(void)
7660+
{
7661+
bool brace = IS_ENABLED(CONFIG_PREEMPT_RT) &&
7662+
(IS_ENABLED(CONFIG_PREEMPT_DYNAMIC) ||
7663+
IS_ENABLED(CONFIG_PREEMPT_LAZY));
7664+
static char buf[128];
7665+
7666+
if (IS_ENABLED(CONFIG_PREEMPT_BUILD)) {
7667+
struct seq_buf s;
7668+
7669+
seq_buf_init(&s, buf, sizeof(buf));
7670+
seq_buf_puts(&s, "PREEMPT");
7671+
7672+
if (IS_ENABLED(CONFIG_PREEMPT_RT))
7673+
seq_buf_printf(&s, "%sRT%s",
7674+
brace ? "_{" : "_",
7675+
brace ? "," : "");
7676+
7677+
if (IS_ENABLED(CONFIG_PREEMPT_DYNAMIC)) {
7678+
seq_buf_printf(&s, "(%s)%s",
7679+
preempt_dynamic_mode > 0 ?
7680+
preempt_modes[preempt_dynamic_mode] : "undef",
7681+
brace ? "}" : "");
7682+
return seq_buf_str(&s);
7683+
}
7684+
7685+
if (IS_ENABLED(CONFIG_PREEMPT_LAZY)) {
7686+
seq_buf_printf(&s, "LAZY%s",
7687+
brace ? "}" : "");
7688+
return seq_buf_str(&s);
7689+
}
7690+
7691+
return seq_buf_str(&s);
7692+
}
7693+
7694+
if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY_BUILD))
7695+
return "VOLUNTARY";
7696+
7697+
return "NONE";
7698+
}
7699+
76537700
int io_schedule_prepare(void)
76547701
{
76557702
int old_iowait = current->in_iowait;

kernel/sched/debug.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ static ssize_t sched_dynamic_write(struct file *filp, const char __user *ubuf,
244244

245245
static int sched_dynamic_show(struct seq_file *m, void *v)
246246
{
247-
static const char * preempt_modes[] = {
248-
"none", "voluntary", "full", "lazy",
249-
};
250-
int j = ARRAY_SIZE(preempt_modes) - !IS_ENABLED(CONFIG_ARCH_HAS_PREEMPT_LAZY);
251247
int i = IS_ENABLED(CONFIG_PREEMPT_RT) * 2;
248+
int j;
249+
250+
/* Count entries in NULL terminated preempt_modes */
251+
for (j = 0; preempt_modes[j]; j++)
252+
;
253+
j -= !IS_ENABLED(CONFIG_ARCH_HAS_PREEMPT_LAZY);
252254

253255
for (; i < j; i++) {
254256
if (preempt_dynamic_mode == i)

kernel/sched/sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3633,6 +3633,7 @@ extern int preempt_dynamic_mode;
36333633
extern int sched_dynamic_mode(const char *str);
36343634
extern void sched_dynamic_update(int mode);
36353635
#endif
3636+
extern const char *preempt_modes[];
36363637

36373638
#ifdef CONFIG_SCHED_MM_CID
36383639

0 commit comments

Comments
 (0)