blob: ef6ad9e1a609d85d751268b4c8911706476b723b [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>
18#include <asm/alternative-asm.i>
19#include <asm/frame.i>
20#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
155/* Fix up special calling conventions */
156ENTRY(call_rwsem_down_read_failed)
157 CFI_STARTPROC
158 push %ecx
159 CFI_ADJUST_CFA_OFFSET 4
160 CFI_REL_OFFSET ecx,0
161 push %edx
162 CFI_ADJUST_CFA_OFFSET 4
163 CFI_REL_OFFSET edx,0
164 call rwsem_down_read_failed
165 pop %edx
166 CFI_ADJUST_CFA_OFFSET -4
167 pop %ecx
168 CFI_ADJUST_CFA_OFFSET -4
169 ret
170 CFI_ENDPROC
171 END(call_rwsem_down_read_failed)
172
173ENTRY(call_rwsem_down_write_failed)
174 CFI_STARTPROC
175 push %ecx
176 CFI_ADJUST_CFA_OFFSET 4
177 CFI_REL_OFFSET ecx,0
178 calll rwsem_down_write_failed
179 pop %ecx
180 CFI_ADJUST_CFA_OFFSET -4
181 ret
182 CFI_ENDPROC
183 END(call_rwsem_down_write_failed)
184
185ENTRY(call_rwsem_wake)
186 CFI_STARTPROC
187 decw %dx /* do nothing if still outstanding active readers */
188 jnz 1f
189 push %ecx
190 CFI_ADJUST_CFA_OFFSET 4
191 CFI_REL_OFFSET ecx,0
192 call rwsem_wake
193 pop %ecx
194 CFI_ADJUST_CFA_OFFSET -4
1951: ret
196 CFI_ENDPROC
197 END(call_rwsem_wake)
198
199/* Fix up special calling conventions */
200ENTRY(call_rwsem_downgrade_wake)
201 CFI_STARTPROC
202 push %ecx
203 CFI_ADJUST_CFA_OFFSET 4
204 CFI_REL_OFFSET ecx,0
205 push %edx
206 CFI_ADJUST_CFA_OFFSET 4
207 CFI_REL_OFFSET edx,0
208 call rwsem_downgrade_wake
209 pop %edx
210 CFI_ADJUST_CFA_OFFSET -4
211 pop %ecx
212 CFI_ADJUST_CFA_OFFSET -4
213 ret
214 CFI_ENDPROC
215 END(call_rwsem_downgrade_wake)
216