aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-03-05 10:46:38 +0100
committerIngo Molnar <mingo@elte.hu>2008-04-17 17:40:52 +0200
commit8b6451fe5cf78909f28d3762f77df060c8603cd0 (patch)
treea9e6a3a9f79877675a1855469ed98677db771797 /include
parent23b55bd9f33a1812a664e548803db34c9bec56e8 (diff)
x86: fix switch_to() clobbers
Liu Pingfan noticed that switch_to() clobbers more registers than its asm constraints specify. We get away with this due to luck mostly - schedule() by its nature only has 'local' state which gets reloaded automatically. Fix it nevertheless, we could hit this anytime. it turns out that with the extra constraints gcc manages to make schedule() even more compact: text data bss dec hex filename 28626 684 2640 31950 7cce sched.o.before 28613 684 2640 31937 7cc1 sched.o.after Reported-by: Liu Pingfan <kernelfans@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/asm-x86/system.h10
1 files changed, 9 insertions, 1 deletions
diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h
index 299ae9605cb..33b0017156a 100644
--- a/include/asm-x86/system.h
+++ b/include/asm-x86/system.h
@@ -29,7 +29,14 @@ struct task_struct *__switch_to(struct task_struct *prev,
*/
#define switch_to(prev, next, last) \
do { \
- unsigned long esi, edi; \
+ /* \
+ * Context-switching clobbers all registers, so we clobber \
+ * them explicitly, via unused output variables. \
+ * (EAX and EBP is not listed because EBP is saved/restored \
+ * explicitly for wchan access and EAX is the return value of \
+ * __switch_to()) \
+ */ \
+ unsigned long ebx, ecx, edx, esi, edi; \
\
asm volatile( \
"pushfl \n\t" /* save flags */ \
@@ -49,6 +56,7 @@ do { \
"=a" (last), \
\
/* clobbered output registers: */ \
+ "=b" (ebx), "=c" (ecx), "=d" (edx), \
"=S" (esi), "=D" (edi) \
\
/* input parameters: */ \