blob: dfd6b814d378101336e1241166c0c3605cb2f0d7 [file] [log] [blame]
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