diff options
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 571f9fe490ce..59be85d9a4bc 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -86,12 +86,22 @@ EXPORT_SYMBOL(enable_hlt); | |||
86 | */ | 86 | */ |
87 | void default_idle(void) | 87 | void default_idle(void) |
88 | { | 88 | { |
89 | local_irq_enable(); | ||
90 | |||
89 | if (!atomic_read(&hlt_counter)) { | 91 | if (!atomic_read(&hlt_counter)) { |
90 | local_irq_disable(); | 92 | clear_thread_flag(TIF_POLLING_NRFLAG); |
91 | if (!need_resched()) | 93 | smp_mb__after_clear_bit(); |
92 | safe_halt(); | 94 | while (!need_resched()) { |
93 | else | 95 | local_irq_disable(); |
94 | local_irq_enable(); | 96 | if (!need_resched()) |
97 | safe_halt(); | ||
98 | else | ||
99 | local_irq_enable(); | ||
100 | } | ||
101 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
102 | } else { | ||
103 | while (!need_resched()) | ||
104 | cpu_relax(); | ||
95 | } | 105 | } |
96 | } | 106 | } |
97 | 107 | ||
@@ -102,30 +112,16 @@ void default_idle(void) | |||
102 | */ | 112 | */ |
103 | static void poll_idle (void) | 113 | static void poll_idle (void) |
104 | { | 114 | { |
105 | int oldval; | ||
106 | |||
107 | local_irq_enable(); | 115 | local_irq_enable(); |
108 | 116 | ||
109 | /* | 117 | asm volatile( |
110 | * Deal with another CPU just having chosen a thread to | 118 | "2:" |
111 | * run here: | 119 | "testl %0,%1;" |
112 | */ | 120 | "rep; nop;" |
113 | oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); | 121 | "je 2b;" |
114 | 122 | : : | |
115 | if (!oldval) { | 123 | "i" (_TIF_NEED_RESCHED), |
116 | set_thread_flag(TIF_POLLING_NRFLAG); | 124 | "m" (current_thread_info()->flags)); |
117 | asm volatile( | ||
118 | "2:" | ||
119 | "testl %0,%1;" | ||
120 | "rep; nop;" | ||
121 | "je 2b;" | ||
122 | : : | ||
123 | "i" (_TIF_NEED_RESCHED), | ||
124 | "m" (current_thread_info()->flags)); | ||
125 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
126 | } else { | ||
127 | set_need_resched(); | ||
128 | } | ||
129 | } | 125 | } |
130 | 126 | ||
131 | void cpu_idle_wait(void) | 127 | void cpu_idle_wait(void) |
@@ -187,6 +183,8 @@ static inline void play_dead(void) | |||
187 | */ | 183 | */ |
188 | void cpu_idle (void) | 184 | void cpu_idle (void) |
189 | { | 185 | { |
186 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
187 | |||
190 | /* endless idle loop with no priority at all */ | 188 | /* endless idle loop with no priority at all */ |
191 | while (1) { | 189 | while (1) { |
192 | while (!need_resched()) { | 190 | while (!need_resched()) { |
@@ -221,15 +219,12 @@ static void mwait_idle(void) | |||
221 | { | 219 | { |
222 | local_irq_enable(); | 220 | local_irq_enable(); |
223 | 221 | ||
224 | if (!need_resched()) { | 222 | while (!need_resched()) { |
225 | set_thread_flag(TIF_POLLING_NRFLAG); | 223 | __monitor((void *)¤t_thread_info()->flags, 0, 0); |
226 | do { | 224 | smp_mb(); |
227 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 225 | if (need_resched()) |
228 | if (need_resched()) | 226 | break; |
229 | break; | 227 | __mwait(0, 0); |
230 | __mwait(0, 0); | ||
231 | } while (!need_resched()); | ||
232 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
233 | } | 228 | } |
234 | } | 229 | } |
235 | 230 | ||