linux/arch/i386/lib/semaphore.S
Andi Kleen add659bf8a [PATCH] i386: Remove lock section support in rwsem.h
Lock sections don't work the new dwarf2 unwinder
This generates slightly smaller code. It adds one more taken
jump to the fast path.

Also move the trampolines into semaphore.S and add proper CFI
annotations.

Cc: jbeulich@novell.com

Signed-off-by: Andi Kleen <ak@suse.de>
2006-09-26 10:52:31 +02:00

218 lines
4.1 KiB
ArmAsm

/*
* i386 semaphore implementation.
*
* (C) Copyright 1999 Linus Torvalds
*
* Portions Copyright 1999 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/rwlock.h>
#include <asm/alternative-asm.i>
#include <asm/frame.i>
#include <asm/dwarf2.h>
/*
* The semaphore operations have a special calling sequence that
* allow us to do a simpler in-line version of them. These routines
* need to convert that sequence back into the C sequence when
* there is contention on the semaphore.
*
* %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..
*/
.section .sched.text
ENTRY(__down_failed)
CFI_STARTPROC
FRAME
pushl %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
pushl %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
call __down
popl %ecx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE ecx
popl %edx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE edx
ENDFRAME
ret
CFI_ENDPROC
END(__down_failed)
ENTRY(__down_failed_interruptible)
CFI_STARTPROC
FRAME
pushl %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
pushl %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
call __down_interruptible
popl %ecx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE ecx
popl %edx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE edx
ENDFRAME
ret
CFI_ENDPROC
END(__down_failed_interruptible)
ENTRY(__down_failed_trylock)
CFI_STARTPROC
FRAME
pushl %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
pushl %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
call __down_trylock
popl %ecx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE ecx
popl %edx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE edx
ENDFRAME
ret
CFI_ENDPROC
END(__down_failed_trylock)
ENTRY(__up_wakeup)
CFI_STARTPROC
FRAME
pushl %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
pushl %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
call __up
popl %ecx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE ecx
popl %edx
CFI_ADJUST_CFA_OFFSET -4
CFI_RESTORE edx
ENDFRAME
ret
CFI_ENDPROC
END(__up_wakeup)
/*
* rw spinlock fallbacks
*/
#ifdef CONFIG_SMP
ENTRY(__write_lock_failed)
CFI_STARTPROC simple
FRAME
2: LOCK_PREFIX
addl $ RW_LOCK_BIAS,(%eax)
1: rep; nop
cmpl $ RW_LOCK_BIAS,(%eax)
jne 1b
LOCK_PREFIX
subl $ RW_LOCK_BIAS,(%eax)
jnz 2b
ENDFRAME
ret
CFI_ENDPROC
END(__write_lock_failed)
ENTRY(__read_lock_failed)
CFI_STARTPROC
FRAME
2: LOCK_PREFIX
incl (%eax)
1: rep; nop
cmpl $1,(%eax)
js 1b
LOCK_PREFIX
decl (%eax)
js 2b
ENDFRAME
ret
CFI_ENDPROC
END(__read_lock_failed)
#endif
/* Fix up special calling conventions */
ENTRY(call_rwsem_down_read_failed)
CFI_STARTPROC
push %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
push %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
call rwsem_down_read_failed
pop %edx
CFI_ADJUST_CFA_OFFSET -4
pop %ecx
CFI_ADJUST_CFA_OFFSET -4
ret
CFI_ENDPROC
END(call_rwsem_down_read_failed)
ENTRY(call_rwsem_down_write_failed)
CFI_STARTPROC
push %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
calll rwsem_down_write_failed
pop %ecx
CFI_ADJUST_CFA_OFFSET -4
ret
CFI_ENDPROC
END(call_rwsem_down_write_failed)
ENTRY(call_rwsem_wake)
CFI_STARTPROC
decw %dx /* do nothing if still outstanding active readers */
jnz 1f
push %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
call rwsem_wake
pop %ecx
CFI_ADJUST_CFA_OFFSET -4
1: ret
CFI_ENDPROC
END(call_rwsem_wake)
/* Fix up special calling conventions */
ENTRY(call_rwsem_downgrade_wake)
CFI_STARTPROC
push %ecx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET ecx,0
push %edx
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET edx,0
call rwsem_downgrade_wake
pop %edx
CFI_ADJUST_CFA_OFFSET -4
pop %ecx
CFI_ADJUST_CFA_OFFSET -4
ret
CFI_ENDPROC
END(call_rwsem_downgrade_wake)