summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-28 23:50:26 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-28 23:50:26 -0700
commitb5d748ca0a00a7cf495d9a255625480dce9f267f (patch)
tree6d4bed65b4e2d12e0b14ac008b28ac82b0378a69
parentde553d73a0c3588106f4c318af5e86c1f0d8fddd (diff)
Make x86 semaphore routines use register calling convention.
This avoids a bug where the compiler would overwrite the stackframe that the caller also considered to be a register save area. It also shrinks the code segment by a tiny amount by moving the failure case argument setup into the slow path. This not only makes the fast path smaller, but it makes it easier on gcc (gcc is not very good at generating code that uses fixed register names).
-rw-r--r--arch/i386/kernel/semaphore.c18
-rw-r--r--include/asm-i386/semaphore.h40
-rw-r--r--include/linux/spinlock.h2
3 files changed, 30 insertions, 30 deletions
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
index 073912cfcf44..be61aa8af188 100644
--- a/arch/i386/kernel/semaphore.c
+++ b/arch/i386/kernel/semaphore.c
@@ -49,12 +49,12 @@
* we cannot lose wakeup events.
*/
-asmlinkage void __up(struct semaphore *sem)
+fastcall void __up(struct semaphore *sem)
{
wake_up(&sem->wait);
}
-asmlinkage void __sched __down(struct semaphore * sem)
+fastcall void __sched __down(struct semaphore * sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
@@ -91,7 +91,7 @@ asmlinkage void __sched __down(struct semaphore * sem)
tsk->state = TASK_RUNNING;
}
-asmlinkage int __sched __down_interruptible(struct semaphore * sem)
+fastcall int __sched __down_interruptible(struct semaphore * sem)
{
int retval = 0;
struct task_struct *tsk = current;
@@ -154,7 +154,7 @@ asmlinkage int __sched __down_interruptible(struct semaphore * sem)
* single "cmpxchg" without failure cases,
* but then it wouldn't work on a 386.
*/
-asmlinkage int __down_trylock(struct semaphore * sem)
+fastcall int __down_trylock(struct semaphore * sem)
{
int sleepers;
unsigned long flags;
@@ -183,9 +183,9 @@ asmlinkage int __down_trylock(struct semaphore * sem)
* need to convert that sequence back into the C sequence when
* there is contention on the semaphore.
*
- * %ecx contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax when used as a return
- * value..
+ * %eax contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax whish is either a return
+ * value or just clobbered..
*/
asm(
".section .sched.text\n"
@@ -196,13 +196,11 @@ asm(
"pushl %ebp\n\t"
"movl %esp,%ebp\n\t"
#endif
- "pushl %eax\n\t"
"pushl %edx\n\t"
"pushl %ecx\n\t"
"call __down\n\t"
"popl %ecx\n\t"
"popl %edx\n\t"
- "popl %eax\n\t"
#if defined(CONFIG_FRAME_POINTER)
"movl %ebp,%esp\n\t"
"popl %ebp\n\t"
@@ -257,13 +255,11 @@ asm(
".align 4\n"
".globl __up_wakeup\n"
"__up_wakeup:\n\t"
- "pushl %eax\n\t"
"pushl %edx\n\t"
"pushl %ecx\n\t"
"call __up\n\t"
"popl %ecx\n\t"
"popl %edx\n\t"
- "popl %eax\n\t"
"ret"
);
diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
index 1db03a68622d..1452af116f92 100644
--- a/include/asm-i386/semaphore.h
+++ b/include/asm-i386/semaphore.h
@@ -87,15 +87,15 @@ static inline void init_MUTEX_LOCKED (struct semaphore *sem)
sema_init(sem, 0);
}
-asmlinkage void __down_failed(void /* special register calling convention */);
-asmlinkage int __down_failed_interruptible(void /* params in registers */);
-asmlinkage int __down_failed_trylock(void /* params in registers */);
-asmlinkage void __up_wakeup(void /* special register calling convention */);
+fastcall void __down_failed(void /* special register calling convention */);
+fastcall int __down_failed_interruptible(void /* params in registers */);
+fastcall int __down_failed_trylock(void /* params in registers */);
+fastcall void __up_wakeup(void /* special register calling convention */);
-asmlinkage void __down(struct semaphore * sem);
-asmlinkage int __down_interruptible(struct semaphore * sem);
-asmlinkage int __down_trylock(struct semaphore * sem);
-asmlinkage void __up(struct semaphore * sem);
+fastcall void __down(struct semaphore * sem);
+fastcall int __down_interruptible(struct semaphore * sem);
+fastcall int __down_trylock(struct semaphore * sem);
+fastcall void __up(struct semaphore * sem);
/*
* This is ugly, but we want the default case to fall through.
@@ -111,12 +111,13 @@ static inline void down(struct semaphore * sem)
"js 2f\n"
"1:\n"
LOCK_SECTION_START("")
- "2:\tcall __down_failed\n\t"
+ "2:\tlea %0,%%eax\n\t"
+ "call __down_failed\n\t"
"jmp 1b\n"
LOCK_SECTION_END
:"=m" (sem->count)
- :"c" (sem)
- :"memory");
+ :
+ :"memory","ax");
}
/*
@@ -135,11 +136,12 @@ static inline int down_interruptible(struct semaphore * sem)
"xorl %0,%0\n"
"1:\n"
LOCK_SECTION_START("")
- "2:\tcall __down_failed_interruptible\n\t"
+ "2:\tlea %1,%%eax\n\t"
+ "call __down_failed_interruptible\n\t"
"jmp 1b\n"
LOCK_SECTION_END
:"=a" (result), "=m" (sem->count)
- :"c" (sem)
+ :
:"memory");
return result;
}
@@ -159,11 +161,12 @@ static inline int down_trylock(struct semaphore * sem)
"xorl %0,%0\n"
"1:\n"
LOCK_SECTION_START("")
- "2:\tcall __down_failed_trylock\n\t"
+ "2:\tlea %1,%%eax\n\t"
+ "call __down_failed_trylock\n\t"
"jmp 1b\n"
LOCK_SECTION_END
:"=a" (result), "=m" (sem->count)
- :"c" (sem)
+ :
:"memory");
return result;
}
@@ -182,13 +185,14 @@ static inline void up(struct semaphore * sem)
"jle 2f\n"
"1:\n"
LOCK_SECTION_START("")
- "2:\tcall __up_wakeup\n\t"
+ "2:\tlea %0,%%eax\n\t"
+ "call __up_wakeup\n\t"
"jmp 1b\n"
LOCK_SECTION_END
".subsection 0\n"
:"=m" (sem->count)
- :"c" (sem)
- :"memory");
+ :
+ :"memory","ax");
}
#endif
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index bebb94a4dec0..81d975639389 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -27,7 +27,7 @@
extra \
".ifndef " LOCK_SECTION_NAME "\n\t" \
LOCK_SECTION_NAME ":\n\t" \
- ".endif\n\t"
+ ".endif\n"
#define LOCK_SECTION_END \
".previous\n\t"