This is a horrible way to detect whether a task has been preempted. Come up with something better: task flag? or is there already an existing mechanism? Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> --- include/linux/sched.h | 11 ++++++++++- kernel/sched/core.c | 26 ++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 589c478..62d0961 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3239,4 +3239,13 @@ struct update_util_data { void cpufreq_set_update_util_data(int cpu, struct update_util_data *data); #endif /* CONFIG_CPU_FREQ */ -#endif +#ifdef CONFIG_PREEMPT +extern bool in_preempt_schedule_irq(unsigned long addr); +#else +static inline bool in_preempt_schedule_irq(unsigned long addr) +{ + return false; +} +#endif /* CONFIG_PREEMPT */ + +#endif /* _LINUX_SCHED_H */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d8465ee..be1ef22 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3334,8 +3334,6 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) } EXPORT_SYMBOL_GPL(preempt_schedule_notrace); -#endif /* CONFIG_PREEMPT */ - /* * this is the entry point to schedule() from kernel preemption * off of irq context. @@ -3360,8 +3358,32 @@ asmlinkage __visible void __sched preempt_schedule_irq(void) } while (need_resched()); exception_exit(prev_state); + + asm("preempt_schedule_irq_end:"); } +/* + * in_preempt_schedule_irq - determine if instruction address is inside the + * preempt_schedule_irq() function + * + * This is used when walking the stack of a task to determine whether an + * interrupt frame exists. + * + * NOTE: This function could return false if the address is in the function + * epilogue. But it's good enough for our purposes, because we only care about + * addresses which have been saved on a stack. If preempt_schedule_irq() is on + * the stack of a task, the saved address will always be prior to the epilogue. + */ +bool in_preempt_schedule_irq(unsigned long addr) +{ + extern void *preempt_schedule_irq_end; + + return (addr >= (unsigned long)preempt_schedule_irq && + addr < (unsigned long)preempt_schedule_irq_end); +} + +#endif /* CONFIG_PREEMPT */ + int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags, void *key) { -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe live-patching" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html