Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754367AbcCYTgP (ORCPT ); Fri, 25 Mar 2016 15:36:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41290 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754319AbcCYTgN (ORCPT ); Fri, 25 Mar 2016 15:36:13 -0400 From: Josh Poimboeuf To: Jiri Kosina , Jessica Yu , Miroslav Benes Cc: linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, Vojtech Pavlik Subject: [RFC PATCH v1.9 05/14] sched: horrible way to detect whether a task has been preempted Date: Fri, 25 Mar 2016 14:34:52 -0500 Message-Id: <24db5a6ae5b63dfcd2096a12d18e1399a351348e.1458933243.git.jpoimboe@redhat.com> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2405 Lines: 77 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 --- 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