diff options
author | David S. Miller <davem@davemloft.net> | 2008-04-18 02:56:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-18 02:56:30 -0400 |
commit | 1e42198609d73ed1a9adcba2af275c24c2678420 (patch) | |
tree | 32fd4d9073bfc0f3909af8f9fb4bcff38951d01a /arch/x86/kernel/process_64.c | |
parent | 794eb6bf20ebf992c040ea831cd3a9c64b0c1f7a (diff) | |
parent | 4b119e21d0c66c22e8ca03df05d9de623d0eb50f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/x86/kernel/process_64.c')
-rw-r--r-- | arch/x86/kernel/process_64.c | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3baf9b9f4c87..46c4c546b499 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -63,7 +63,6 @@ EXPORT_SYMBOL(boot_option_idle_override); | |||
63 | */ | 63 | */ |
64 | void (*pm_idle)(void); | 64 | void (*pm_idle)(void); |
65 | EXPORT_SYMBOL(pm_idle); | 65 | EXPORT_SYMBOL(pm_idle); |
66 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); | ||
67 | 66 | ||
68 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); | 67 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
69 | 68 | ||
@@ -173,9 +172,6 @@ void cpu_idle(void) | |||
173 | while (!need_resched()) { | 172 | while (!need_resched()) { |
174 | void (*idle)(void); | 173 | void (*idle)(void); |
175 | 174 | ||
176 | if (__get_cpu_var(cpu_idle_state)) | ||
177 | __get_cpu_var(cpu_idle_state) = 0; | ||
178 | |||
179 | rmb(); | 175 | rmb(); |
180 | idle = pm_idle; | 176 | idle = pm_idle; |
181 | if (!idle) | 177 | if (!idle) |
@@ -207,40 +203,19 @@ static void do_nothing(void *unused) | |||
207 | { | 203 | { |
208 | } | 204 | } |
209 | 205 | ||
206 | /* | ||
207 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
208 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
209 | * handler on SMP systems. | ||
210 | * | ||
211 | * Caller must have changed pm_idle to the new value before the call. Old | ||
212 | * pm_idle value will not be used by any CPU after the return of this function. | ||
213 | */ | ||
210 | void cpu_idle_wait(void) | 214 | void cpu_idle_wait(void) |
211 | { | 215 | { |
212 | unsigned int cpu, this_cpu = get_cpu(); | 216 | smp_mb(); |
213 | cpumask_t map, tmp = current->cpus_allowed; | 217 | /* kick all the CPUs so that they exit out of pm_idle */ |
214 | 218 | smp_call_function(do_nothing, NULL, 0, 1); | |
215 | set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); | ||
216 | put_cpu(); | ||
217 | |||
218 | cpus_clear(map); | ||
219 | for_each_online_cpu(cpu) { | ||
220 | per_cpu(cpu_idle_state, cpu) = 1; | ||
221 | cpu_set(cpu, map); | ||
222 | } | ||
223 | |||
224 | __get_cpu_var(cpu_idle_state) = 0; | ||
225 | |||
226 | wmb(); | ||
227 | do { | ||
228 | ssleep(1); | ||
229 | for_each_online_cpu(cpu) { | ||
230 | if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu)) | ||
231 | cpu_clear(cpu, map); | ||
232 | } | ||
233 | cpus_and(map, map, cpu_online_map); | ||
234 | /* | ||
235 | * We waited 1 sec, if a CPU still did not call idle | ||
236 | * it may be because it is in idle and not waking up | ||
237 | * because it has nothing to do. | ||
238 | * Give all the remaining CPUS a kick. | ||
239 | */ | ||
240 | smp_call_function_mask(map, do_nothing, 0, 0); | ||
241 | } while (!cpus_empty(map)); | ||
242 | |||
243 | set_cpus_allowed(current, tmp); | ||
244 | } | 219 | } |
245 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | 220 | EXPORT_SYMBOL_GPL(cpu_idle_wait); |
246 | 221 | ||