blob: 444fba4009837d45971d6038e6c50851202856b0 [file] [log] [blame]
Andi Kleenecaf45e2006-09-26 10:52:29 +02001/*
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 */
15
Andi Kleenecaf45e2006-09-26 10:52:29 +020016#include <linux/linkage.h>
17#include <asm/rwlock.h>
Adrian Bunk7e02cb92007-10-17 18:04:38 +020018#include <asm/alternative-asm.h>
19#include <asm/frame.h>
Andi Kleenecaf45e2006-09-26 10:52:29 +020020#include <asm/dwarf2.h>
21
22/*
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
33ENTRY(__down_failed)
34 CFI_STARTPROC
35 FRAME
36 pushl %edx
37 CFI_ADJUST_CFA_OFFSET 4
38 CFI_REL_OFFSET edx,0
39 pushl %ecx
40 CFI_ADJUST_CFA_OFFSET 4
41 CFI_REL_OFFSET ecx,0
42 call __down
43 popl %ecx
44 CFI_ADJUST_CFA_OFFSET -4
45 CFI_RESTORE ecx
46 popl %edx
47 CFI_ADJUST_CFA_OFFSET -4
48 CFI_RESTORE edx
49 ENDFRAME
50 ret
51 CFI_ENDPROC
52 END(__down_failed)
53
54ENTRY(__down_failed_interruptible)
55 CFI_STARTPROC
56 FRAME
57 pushl %edx
58 CFI_ADJUST_CFA_OFFSET 4
59 CFI_REL_OFFSET edx,0
60 pushl %ecx
61 CFI_ADJUST_CFA_OFFSET 4
62 CFI_REL_OFFSET ecx,0
63 call __down_interruptible
64 popl %ecx
65 CFI_ADJUST_CFA_OFFSET -4
66 CFI_RESTORE ecx
67 popl %edx
68 CFI_ADJUST_CFA_OFFSET -4
69 CFI_RESTORE edx
70 ENDFRAME
71 ret
72 CFI_ENDPROC
73 END(__down_failed_interruptible)
74
75ENTRY(__down_failed_trylock)
76 CFI_STARTPROC
77 FRAME
78 pushl %edx
79 CFI_ADJUST_CFA_OFFSET 4
80 CFI_REL_OFFSET edx,0
81 pushl %ecx
82 CFI_ADJUST_CFA_OFFSET 4
83 CFI_REL_OFFSET ecx,0
84 call __down_trylock
85 popl %ecx
86 CFI_ADJUST_CFA_OFFSET -4
87 CFI_RESTORE ecx
88 popl %edx
89 CFI_ADJUST_CFA_OFFSET -4
90 CFI_RESTORE edx
91 ENDFRAME
92 ret
93 CFI_ENDPROC
94 END(__down_failed_trylock)
95
96ENTRY(__up_wakeup)
97 CFI_STARTPROC
98 FRAME
99 pushl %edx
100 CFI_ADJUST_CFA_OFFSET 4
101 CFI_REL_OFFSET edx,0
102 pushl %ecx
103 CFI_ADJUST_CFA_OFFSET 4
104 CFI_REL_OFFSET ecx,0
105 call __up
106 popl %ecx
107 CFI_ADJUST_CFA_OFFSET -4
108 CFI_RESTORE ecx
109 popl %edx
110 CFI_ADJUST_CFA_OFFSET -4
111 CFI_RESTORE edx
112 ENDFRAME
113 ret
114 CFI_ENDPROC
115 END(__up_wakeup)
116
117/*
118 * rw spinlock fallbacks
119 */
120#ifdef CONFIG_SMP
121ENTRY(__write_lock_failed)
122 CFI_STARTPROC simple
123 FRAME
1242: LOCK_PREFIX
125 addl $ RW_LOCK_BIAS,(%eax)
1261: rep; nop
127 cmpl $ RW_LOCK_BIAS,(%eax)
128 jne 1b
129 LOCK_PREFIX
130 subl $ RW_LOCK_BIAS,(%eax)
131 jnz 2b
132 ENDFRAME
133 ret
134 CFI_ENDPROC
135 END(__write_lock_failed)
136
137ENTRY(__read_lock_failed)
138 CFI_STARTPROC
139 FRAME
1402: LOCK_PREFIX
141 incl (%eax)
1421: rep; nop
143 cmpl $1,(%eax)
144 js 1b
145 LOCK_PREFIX
146 decl (%eax)
147 js 2b
148 ENDFRAME
149 ret
150 CFI_ENDPROC
151 END(__read_lock_failed)
152
153#endif
Andi Kleenadd659b2006-09-26 10:52:31 +0200154
Ingo Molnar88271e92006-10-05 18:47:22 +0200155#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
156
Andi Kleenadd659b2006-09-26 10:52:31 +0200157/* Fix up special calling conventions */
158ENTRY(call_rwsem_down_read_failed)
159 CFI_STARTPROC
160 push %ecx
161 CFI_ADJUST_CFA_OFFSET 4
162 CFI_REL_OFFSET ecx,0
163 push %edx
164 CFI_ADJUST_CFA_OFFSET 4
165 CFI_REL_OFFSET edx,0
166 call rwsem_down_read_failed
167 pop %edx
168 CFI_ADJUST_CFA_OFFSET -4
169 pop %ecx
170 CFI_ADJUST_CFA_OFFSET -4
171 ret
172 CFI_ENDPROC
173 END(call_rwsem_down_read_failed)
174
175ENTRY(call_rwsem_down_write_failed)
176 CFI_STARTPROC
177 push %ecx
178 CFI_ADJUST_CFA_OFFSET 4
179 CFI_REL_OFFSET ecx,0
180 calll rwsem_down_write_failed
181 pop %ecx
182 CFI_ADJUST_CFA_OFFSET -4
183 ret
184 CFI_ENDPROC
185 END(call_rwsem_down_write_failed)
186
187ENTRY(call_rwsem_wake)
188 CFI_STARTPROC
189 decw %dx /* do nothing if still outstanding active readers */
190 jnz 1f
191 push %ecx
192 CFI_ADJUST_CFA_OFFSET 4
193 CFI_REL_OFFSET ecx,0
194 call rwsem_wake
195 pop %ecx
196 CFI_ADJUST_CFA_OFFSET -4
1971: ret
198 CFI_ENDPROC
199 END(call_rwsem_wake)
200
201/* Fix up special calling conventions */
202ENTRY(call_rwsem_downgrade_wake)
203 CFI_STARTPROC
204 push %ecx
205 CFI_ADJUST_CFA_OFFSET 4
206 CFI_REL_OFFSET ecx,0
207 push %edx
208 CFI_ADJUST_CFA_OFFSET 4
209 CFI_REL_OFFSET edx,0
210 call rwsem_downgrade_wake
211 pop %edx
212 CFI_ADJUST_CFA_OFFSET -4
213 pop %ecx
214 CFI_ADJUST_CFA_OFFSET -4
215 ret
216 CFI_ENDPROC
217 END(call_rwsem_downgrade_wake)
218
Ingo Molnar88271e92006-10-05 18:47:22 +0200219#endif