diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-07-20 14:30:57 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-07-20 19:11:56 +0200 |
commit | 8e7dbdf187d6a6896873a32537fed62111a5910e (patch) | |
tree | 0d104ad7adec643295e991328918e25fbedb5cf1 | |
parent | 5706af4a7052a5048f3e4a2cbc65ee66c71bdfa8 (diff) | |
download | lwn-8e7dbdf187d6a6896873a32537fed62111a5910e.tar.gz lwn-8e7dbdf187d6a6896873a32537fed62111a5910e.zip |
cpu-hotplug: Don't wake up the desched thread from idle_task_exit()
When idle tasks exits then we do not want to wake the cpu bound
desched thread.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | include/linux/sched.h | 6 | ||||
-rw-r--r-- | kernel/fork.c | 23 | ||||
-rw-r--r-- | kernel/sched.c | 4 |
3 files changed, 19 insertions, 14 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 82d06e3ed04b..4610e2c769a3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2290,7 +2290,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) { @@ -2298,10 +2298,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 ebe00bafe70e..1d4acdf6d708 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1803,24 +1803,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; } @@ -1829,7 +1831,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 *desched_task; struct list_head *head; @@ -1837,7 +1839,7 @@ void __mmdrop_delayed(struct mm_struct *mm) head = &get_cpu_var(delayed_drop_list); list_add_tail(&mm->delayed_drop, head); desched_task = __get_cpu_var(desched_task); - if (desched_task) + if (desched_task && wake) wake_up_process(desched_task); put_cpu_var(delayed_drop_list); } @@ -1852,13 +1854,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; @@ -1867,7 +1872,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 bbc181fee05d..056167771b9c 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 @@ -7814,7 +7814,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 |