radix-tree: fix small lockless radix-tree bug
[linux-2.6/pdupreez.git] / arch / x86 / lib / semaphore_32.S
blob648fe474178234e24d2c688bd44756ba24e75b4e
1 /*
2  * i386 semaphore implementation.
3  *
4  * (C) Copyright 1999 Linus Torvalds
5  *
6  * Portions Copyright 1999 Red Hat, Inc.
7  *
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License
10  *      as published by the Free Software Foundation; either version
11  *      2 of the License, or (at your option) any later version.
12  *
13  * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
14  */
16 #include <linux/linkage.h>
17 #include <asm/rwlock.h>
18 #include <asm/alternative-asm.h>
19 #include <asm/frame.h>
20 #include <asm/dwarf2.h>
23  * The semaphore operations have a special calling sequence that
24  * allow us to do a simpler in-line version of them. These routines
25  * need to convert that sequence back into the C sequence when
26  * there is contention on the semaphore.
27  *
28  * %eax contains the semaphore pointer on entry. Save the C-clobbered
29  * registers (%eax, %edx and %ecx) except %eax whish is either a return
30  * value or just clobbered..
31  */
32         .section .sched.text, "ax"
35  * rw spinlock fallbacks
36  */
37 #ifdef CONFIG_SMP
38 ENTRY(__write_lock_failed)
39         CFI_STARTPROC simple
40         FRAME
41 2:      LOCK_PREFIX
42         addl    $ RW_LOCK_BIAS,(%eax)
43 1:      rep; nop
44         cmpl    $ RW_LOCK_BIAS,(%eax)
45         jne     1b
46         LOCK_PREFIX
47         subl    $ RW_LOCK_BIAS,(%eax)
48         jnz     2b
49         ENDFRAME
50         ret
51         CFI_ENDPROC
52         ENDPROC(__write_lock_failed)
54 ENTRY(__read_lock_failed)
55         CFI_STARTPROC
56         FRAME
57 2:      LOCK_PREFIX
58         incl    (%eax)
59 1:      rep; nop
60         cmpl    $1,(%eax)
61         js      1b
62         LOCK_PREFIX
63         decl    (%eax)
64         js      2b
65         ENDFRAME
66         ret
67         CFI_ENDPROC
68         ENDPROC(__read_lock_failed)
70 #endif
72 #ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
74 /* Fix up special calling conventions */
75 ENTRY(call_rwsem_down_read_failed)
76         CFI_STARTPROC
77         push %ecx
78         CFI_ADJUST_CFA_OFFSET 4
79         CFI_REL_OFFSET ecx,0
80         push %edx
81         CFI_ADJUST_CFA_OFFSET 4
82         CFI_REL_OFFSET edx,0
83         call rwsem_down_read_failed
84         pop %edx
85         CFI_ADJUST_CFA_OFFSET -4
86         pop %ecx
87         CFI_ADJUST_CFA_OFFSET -4
88         ret
89         CFI_ENDPROC
90         ENDPROC(call_rwsem_down_read_failed)
92 ENTRY(call_rwsem_down_write_failed)
93         CFI_STARTPROC
94         push %ecx
95         CFI_ADJUST_CFA_OFFSET 4
96         CFI_REL_OFFSET ecx,0
97         calll rwsem_down_write_failed
98         pop %ecx
99         CFI_ADJUST_CFA_OFFSET -4
100         ret
101         CFI_ENDPROC
102         ENDPROC(call_rwsem_down_write_failed)
104 ENTRY(call_rwsem_wake)
105         CFI_STARTPROC
106         decw %dx    /* do nothing if still outstanding active readers */
107         jnz 1f
108         push %ecx
109         CFI_ADJUST_CFA_OFFSET 4
110         CFI_REL_OFFSET ecx,0
111         call rwsem_wake
112         pop %ecx
113         CFI_ADJUST_CFA_OFFSET -4
114 1:      ret
115         CFI_ENDPROC
116         ENDPROC(call_rwsem_wake)
118 /* Fix up special calling conventions */
119 ENTRY(call_rwsem_downgrade_wake)
120         CFI_STARTPROC
121         push %ecx
122         CFI_ADJUST_CFA_OFFSET 4
123         CFI_REL_OFFSET ecx,0
124         push %edx
125         CFI_ADJUST_CFA_OFFSET 4
126         CFI_REL_OFFSET edx,0
127         call rwsem_downgrade_wake
128         pop %edx
129         CFI_ADJUST_CFA_OFFSET -4
130         pop %ecx
131         CFI_ADJUST_CFA_OFFSET -4
132         ret
133         CFI_ENDPROC
134         ENDPROC(call_rwsem_downgrade_wake)
136 #endif