From b60fc07e05f69bce6042ab76ab8e468e6770eb87 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 20 Jul 2010 14:30:57 +0200 Subject: [PATCH] cpu-hotplug: Don't wake up the desched thread from idle_task_exit() commit 8e7dbdf187d6a6896873a32537fed62111a5910e in tip. When idle tasks exits then we do not want to wake the cpu bound desched thread. Signed-off-by: Thomas Gleixner Signed-off-by: Paul Gortmaker --- include/linux/sched.h | 6 +++--- kernel/fork.c | 23 ++++++++++++++--------- kernel/sched.c | 4 ++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index d733a51..f52ece2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2224,7 +2224,7 @@ extern struct mm_struct * mm_alloc(void); /* mmdrop drops the mm and the page tables */ extern void __mmdrop(struct mm_struct *); -extern void __mmdrop_delayed(struct mm_struct *); +extern void __mmdrop_delayed(struct mm_struct *, int wake); static inline void mmdrop(struct mm_struct * mm) { @@ -2232,10 +2232,10 @@ static inline void mmdrop(struct mm_struct * mm) __mmdrop(mm); } -static inline void mmdrop_delayed(struct mm_struct * mm) +static inline void mmdrop_delayed(struct mm_struct * mm, int wake) { if (atomic_dec_and_test(&mm->mm_count)) - __mmdrop_delayed(mm); + __mmdrop_delayed(mm, wake); } /* mmput gets rid of the mappings and all user-space */ diff --git a/kernel/fork.c b/kernel/fork.c index 324cf5c..d0f3c98 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1783,24 +1783,26 @@ int unshare_files(struct files_struct **displaced) return 0; } -static int mmdrop_complete(void) +static int mmdrop_complete(int cpu) { struct list_head *head; int ret = 0; - head = &get_cpu_var(delayed_drop_list); + preempt_disable(); + head = &per_cpu(delayed_drop_list, cpu); while (!list_empty(head)) { struct mm_struct *mm = list_entry(head->next, struct mm_struct, delayed_drop); list_del(&mm->delayed_drop); - put_cpu_var(delayed_drop_list); + preempt_enable(); __mmdrop(mm); ret = 1; - head = &get_cpu_var(delayed_drop_list); + preempt_disable(); + head = &per_cpu(delayed_drop_list, cpu); } - put_cpu_var(delayed_drop_list); + preempt_enable(); return ret; } @@ -1809,7 +1811,7 @@ static int mmdrop_complete(void) * We dont want to do complex work from the scheduler, thus * we delay the work to a per-CPU worker thread: */ -void __mmdrop_delayed(struct mm_struct *mm) +void __mmdrop_delayed(struct mm_struct *mm, int wake) { struct task_struct *cpu_desched_task; struct list_head *head; @@ -1817,7 +1819,7 @@ void __mmdrop_delayed(struct mm_struct *mm) head = &get_cpu_var(delayed_drop_list); list_add_tail(&mm->delayed_drop, head); cpu_desched_task = __get_cpu_var(desched_task); - if (cpu_desched_task) + if (cpu_desched_task && wake) wake_up_process(cpu_desched_task); put_cpu_var(delayed_drop_list); } @@ -1832,13 +1834,16 @@ static void takeover_delayed_drop(int hotcpu) struct mm_struct, delayed_drop); list_del(&mm->delayed_drop); - __mmdrop_delayed(mm); + __mmdrop_delayed(mm, 1); } } #endif static int desched_thread(void * __bind_cpu) { + + int cpu = (unsigned long)__bind_cpu; + set_user_nice(current, -10); current->flags |= PF_NOFREEZE; current->extra_flags |= PFE_SOFTIRQ; @@ -1847,7 +1852,7 @@ static int desched_thread(void * __bind_cpu) while (!kthread_should_stop()) { - if (mmdrop_complete()) + if (mmdrop_complete(cpu)) continue; schedule(); diff --git a/kernel/sched.c b/kernel/sched.c index dd1fc16..82dbca6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2923,7 +2923,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) * to do complex work from within the scheduler: */ if (mm) - mmdrop_delayed(mm); + mmdrop_delayed(mm, 1); if (unlikely(prev_state == TASK_DEAD)) { /* * Remove function-return probe instances associated with this @@ -5959,7 +5959,7 @@ void idle_task_exit(void) if (mm != &init_mm) switch_mm(mm, &init_mm, current); #ifdef CONFIG_PREEMPT_RT - mmdrop_delayed(mm); + mmdrop_delayed(mm, 0); #else mmdrop(mm); #endif -- 1.7.0.4