| From fe22ca5ca9e5d5b5fa6742b7ad40986c8389f155 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| 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 <tglx@linutronix.de> |
| |
| diff --git a/include/linux/sched.h b/include/linux/sched.h |
| index b4f912f..631c0af 100644 |
| --- a/include/linux/sched.h |
| +++ b/include/linux/sched.h |
| @@ -2286,7 +2286,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) |
| { |
| @@ -2294,10 +2294,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 6dc8e27..74192aa 100644 |
| --- a/kernel/fork.c |
| +++ b/kernel/fork.c |
| @@ -1805,24 +1805,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; |
| } |
| @@ -1831,7 +1833,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; |
| @@ -1839,7 +1841,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); |
| } |
| @@ -1854,13 +1856,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; |
| @@ -1869,7 +1874,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 f03f1d2..f8557a5 100644 |
| --- a/kernel/sched.c |
| +++ b/kernel/sched.c |
| @@ -2939,7 +2939,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 |
| @@ -7787,7 +7787,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.1.1 |
| |