| From 26c7295be0c5e6da3fa45970e9748be983175b1b Mon Sep 17 00:00:00 2001 |
| From: Liang Chen <cl@rock-chips.com> |
| Date: Fri, 6 Mar 2020 15:01:33 +0800 |
| Subject: kthread: Do not preempt current task if it is going to call schedule() |
| |
| From: Liang Chen <cl@rock-chips.com> |
| |
| commit 26c7295be0c5e6da3fa45970e9748be983175b1b upstream. |
| |
| when we create a kthread with ktrhead_create_on_cpu(),the child thread |
| entry is ktread.c:ktrhead() which will be preempted by the parent after |
| call complete(done) while schedule() is not called yet,then the parent |
| will call wait_task_inactive(child) but the child is still on the runqueue, |
| so the parent will schedule_hrtimeout() for 1 jiffy,it will waste a lot of |
| time,especially on startup. |
| |
| parent child |
| ktrhead_create_on_cpu() |
| wait_fo_completion(&done) -----> ktread.c:ktrhead() |
| |----- complete(done);--wakeup and preempted by parent |
| kthread_bind() <------------| |-> schedule();--dequeue here |
| wait_task_inactive(child) | |
| schedule_hrtimeout(1 jiffy) -| |
| |
| So we hope the child just wakeup parent but not preempted by parent, and the |
| child is going to call schedule() soon,then the parent will not call |
| schedule_hrtimeout(1 jiffy) as the child is already dequeue. |
| |
| The same issue for ktrhead_park()&&kthread_parkme(). |
| This patch can save 120ms on rk312x startup with CONFIG_HZ=300. |
| |
| Signed-off-by: Liang Chen <cl@rock-chips.com> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| Link: https://lkml.kernel.org/r/20200306070133.18335-2-cl@rock-chips.com |
| Signed-off-by: Chanho Park <chanho61.park@samsung.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| kernel/kthread.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| --- a/kernel/kthread.c |
| +++ b/kernel/kthread.c |
| @@ -190,8 +190,15 @@ static void __kthread_parkme(struct kthr |
| if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags)) |
| break; |
| |
| + /* |
| + * Thread is going to call schedule(), do not preempt it, |
| + * or the caller of kthread_park() may spend more time in |
| + * wait_task_inactive(). |
| + */ |
| + preempt_disable(); |
| complete(&self->parked); |
| - schedule(); |
| + schedule_preempt_disabled(); |
| + preempt_enable(); |
| } |
| __set_current_state(TASK_RUNNING); |
| } |
| @@ -236,8 +243,14 @@ static int kthread(void *_create) |
| /* OK, tell user we're spawned, wait for stop or wakeup */ |
| __set_current_state(TASK_UNINTERRUPTIBLE); |
| create->result = current; |
| + /* |
| + * Thread is going to call schedule(), do not preempt it, |
| + * or the creator may spend more time in wait_task_inactive(). |
| + */ |
| + preempt_disable(); |
| complete(done); |
| - schedule(); |
| + schedule_preempt_disabled(); |
| + preempt_enable(); |
| |
| ret = -EINTR; |
| if (!test_bit(KTHREAD_SHOULD_STOP, &self->flags)) { |