add659bf8a
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>
218 lines
4.1 KiB
ArmAsm
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)
|
|
|