diff options
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index c9df991150bb..669cf0ed3266 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/utsname.h> | 36 | #include <linux/utsname.h> |
37 | #include <linux/random.h> | 37 | #include <linux/random.h> |
38 | #include <linux/kprobes.h> | 38 | #include <linux/kprobes.h> |
39 | #include <linux/notifier.h> | ||
39 | 40 | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
@@ -50,6 +51,7 @@ | |||
50 | #include <asm/desc.h> | 51 | #include <asm/desc.h> |
51 | #include <asm/proto.h> | 52 | #include <asm/proto.h> |
52 | #include <asm/ia32.h> | 53 | #include <asm/ia32.h> |
54 | #include <asm/idle.h> | ||
53 | 55 | ||
54 | asmlinkage extern void ret_from_fork(void); | 56 | asmlinkage extern void ret_from_fork(void); |
55 | 57 | ||
@@ -64,6 +66,50 @@ EXPORT_SYMBOL(boot_option_idle_override); | |||
64 | void (*pm_idle)(void); | 66 | void (*pm_idle)(void); |
65 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); | 67 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); |
66 | 68 | ||
69 | static struct notifier_block *idle_notifier; | ||
70 | static DEFINE_SPINLOCK(idle_notifier_lock); | ||
71 | |||
72 | void idle_notifier_register(struct notifier_block *n) | ||
73 | { | ||
74 | unsigned long flags; | ||
75 | spin_lock_irqsave(&idle_notifier_lock, flags); | ||
76 | notifier_chain_register(&idle_notifier, n); | ||
77 | spin_unlock_irqrestore(&idle_notifier_lock, flags); | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(idle_notifier_register); | ||
80 | |||
81 | void idle_notifier_unregister(struct notifier_block *n) | ||
82 | { | ||
83 | unsigned long flags; | ||
84 | spin_lock_irqsave(&idle_notifier_lock, flags); | ||
85 | notifier_chain_unregister(&idle_notifier, n); | ||
86 | spin_unlock_irqrestore(&idle_notifier_lock, flags); | ||
87 | } | ||
88 | EXPORT_SYMBOL(idle_notifier_unregister); | ||
89 | |||
90 | enum idle_state { CPU_IDLE, CPU_NOT_IDLE }; | ||
91 | static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE; | ||
92 | |||
93 | void enter_idle(void) | ||
94 | { | ||
95 | __get_cpu_var(idle_state) = CPU_IDLE; | ||
96 | notifier_call_chain(&idle_notifier, IDLE_START, NULL); | ||
97 | } | ||
98 | |||
99 | static void __exit_idle(void) | ||
100 | { | ||
101 | __get_cpu_var(idle_state) = CPU_NOT_IDLE; | ||
102 | notifier_call_chain(&idle_notifier, IDLE_END, NULL); | ||
103 | } | ||
104 | |||
105 | /* Called from interrupts to signify idle end */ | ||
106 | void exit_idle(void) | ||
107 | { | ||
108 | if (current->pid | read_pda(irqcount)) | ||
109 | return; | ||
110 | __exit_idle(); | ||
111 | } | ||
112 | |||
67 | /* | 113 | /* |
68 | * We use this if we don't have any better | 114 | * We use this if we don't have any better |
69 | * idle routine.. | 115 | * idle routine.. |
@@ -180,7 +226,9 @@ void cpu_idle (void) | |||
180 | idle = default_idle; | 226 | idle = default_idle; |
181 | if (cpu_is_offline(smp_processor_id())) | 227 | if (cpu_is_offline(smp_processor_id())) |
182 | play_dead(); | 228 | play_dead(); |
229 | enter_idle(); | ||
183 | idle(); | 230 | idle(); |
231 | __exit_idle(); | ||
184 | } | 232 | } |
185 | 233 | ||
186 | preempt_enable_no_resched(); | 234 | preempt_enable_no_resched(); |