linux/arch/i386/lib/semaphore.S
Andi Kleen ecaf45ee5c [PATCH] i386: Redo semaphore and rwlock assembly helpers
- Move them to a pure assembly file. Previously they were in
a C file that only consisted of inline assembly. Doing it in pure
assembler is much nicer.
- Add a frame.i include with FRAME/ENDFRAME macros to easily
add frame pointers to assembly functions
- Add dwarf2 annotation to them so that the new dwarf2 unwinder
doesn't get stuck on them
- Random cleanups

Includes feedback from Jan Beulich and a UML build fix from Andrew
Morton.

Cc: jbeulich@novell.com
Cc: jdike@addtoit.com
Signed-off-by: Andi Kleen <ak@suse.de>
2006-09-26 10:52:29 +02:00

155 lines
2.9 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