Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757700AbcDGVPa (ORCPT ); Thu, 7 Apr 2016 17:15:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44466 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755868AbcDGVP3 (ORCPT ); Thu, 7 Apr 2016 17:15:29 -0400 Date: Thu, 7 Apr 2016 17:15:25 -0400 From: Jessica Yu To: Josh Poimboeuf Cc: Jiri Kosina , Miroslav Benes , linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, Vojtech Pavlik Subject: Re: sched: horrible way to detect whether a task has been preempted Message-ID: <20160407211525.GB25804@packer-debian-8-amd64.digitalocean.com> References: <24db5a6ae5b63dfcd2096a12d18e1399a351348e.1458933243.git.jpoimboe@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: <24db5a6ae5b63dfcd2096a12d18e1399a351348e.1458933243.git.jpoimboe@redhat.com> X-OS: Linux eisen.io 3.16.0-4-amd64 x86_64 User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3271 Lines: 92 +++ Josh Poimboeuf [25/03/16 14:34 -0500]: >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) > { Been sort of rattling my head over the scheduler code :-) Just following the calls in and out of __schedule() it doesn't look like there is a current flag/mechanism to tell whether or not a task has been preempted.. Is there any reason why you didn't just create a new task flag, something like TIF_PREEMPTED_IRQ, which would be set once preempt_schedule_irq() is entered and unset after __schedule() returns (for that task)? This would roughly correspond to setting the task flag when the frame for preempt_schedule_irq() is pushed and unsetting it just before the frame preempt_schedule_irq() is popped for that task. This seems simpler than walking through all the frames just to see if in_preempt_schedule_irq() had been called. Would that work? Jessica