summaryrefslogtreecommitdiffstats
path: root/cpu-hotplug-Don-t-wake-up-the-desched-thread-from-id.patch
blob: c46ae559d02a6266486b0eca52332ab77f9d05ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From b60fc07e05f69bce6042ab76ab8e468e6770eb87 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>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 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