]>
Commit | Line | Data |
---|---|---|
1d087a7e UD |
1 | /* Copyright (C) 2002, 2003 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
19 | ||
20 | #include <sysdep.h> | |
21 | #include <shlib-compat.h> | |
22 | #include <lowlevelcond.h> | |
a7720b5e | 23 | #include <tcb-offsets.h> |
1d087a7e UD |
24 | |
25 | #ifdef UP | |
26 | # define LOCK | |
27 | #else | |
28 | # define LOCK lock | |
29 | #endif | |
30 | ||
31 | #define SYS_futex 240 | |
32 | #define FUTEX_WAIT 0 | |
33 | #define FUTEX_WAKE 1 | |
34 | ||
35 | ||
36 | .text | |
37 | ||
38 | .align 16 | |
39 | .type __condvar_cleanup, @function | |
40 | .globl __condvar_cleanup | |
41 | .hidden __condvar_cleanup | |
42 | __condvar_cleanup: | |
43 | pushl %ebx | |
a7720b5e UD |
44 | pushl %esi |
45 | movl 12(%esp), %esi | |
1d087a7e UD |
46 | |
47 | /* Get internal lock. */ | |
a7720b5e | 48 | movl 4(%esi), %ebx |
1d087a7e UD |
49 | movl $1, %eax |
50 | LOCK | |
51 | #if cond_lock == 0 | |
52 | xaddl %eax, (%ebx) | |
53 | #else | |
54 | xaddl %eax, cond_lock(%ebx) | |
55 | #endif | |
56 | testl %eax, %eax | |
57 | je 1f | |
58 | ||
59 | #if cond_lock == 0 | |
60 | movl %ebx, %ecx | |
61 | #else | |
62 | leal cond_lock(%ebx), %ecx | |
63 | #endif | |
64 | call __lll_mutex_lock_wait | |
65 | ||
3e976b96 UD |
66 | 1: addl $wakeup_seq, %ebx |
67 | addl $1, (%ebx) | |
68 | adcl $0, 4(%ebx) | |
1d087a7e | 69 | |
3e976b96 UD |
70 | addl $1, woken_seq-wakeup_seq(%ebx) |
71 | adcl $0, woken_seq-wakeup_seq+4(%ebx) | |
72 | ||
1d087a7e | 73 | LOCK |
3e976b96 | 74 | subl $1, cond_lock-wakeup_seq(%ebx) |
1d087a7e | 75 | je 2f |
3e976b96 UD |
76 | |
77 | leal cond_lock-wakeup_seq(%ebx), %eax | |
1d087a7e UD |
78 | call __lll_mutex_unlock_wake |
79 | ||
24a49f38 UD |
80 | /* Wake up all waiters to make sure no signal gets lost. */ |
81 | 2: movl $FUTEX_WAKE, %ecx | |
82 | movl $SYS_futex, %eax | |
83 | movl $0x7fffffff, %edx | |
84 | ENTER_KERNEL | |
85 | ||
816a5a6a | 86 | /* Lock the mutex unless asynchronous cancellation is in effect. */ |
ee2af3e8 | 87 | testl $2, 8(%esi) |
a7720b5e UD |
88 | jne 3f |
89 | ||
ee2af3e8 | 90 | pushl (%esi) |
a7720b5e UD |
91 | call __pthread_mutex_lock_internal |
92 | popl %eax | |
93 | ||
94 | 3: popl %esi | |
95 | popl %ebx | |
1d087a7e UD |
96 | ret |
97 | .size __condvar_cleanup, .-__condvar_cleanup | |
98 | ||
99 | ||
100 | /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ | |
101 | .globl __pthread_cond_wait | |
102 | .type __pthread_cond_wait, @function | |
103 | .align 16 | |
104 | __pthread_cond_wait: | |
08c765fa | 105 | .LSTARTCODE: |
1d087a7e UD |
106 | |
107 | pushl %edi | |
08c765fa | 108 | .Lpush_edi: |
1d087a7e | 109 | pushl %esi |
08c765fa | 110 | .Lpush_esi: |
1d087a7e | 111 | pushl %ebx |
08c765fa | 112 | .Lpush_ebx: |
1d087a7e UD |
113 | |
114 | xorl %esi, %esi | |
115 | movl 16(%esp), %ebx | |
1d087a7e UD |
116 | |
117 | /* Get internal lock. */ | |
118 | movl $1, %eax | |
119 | LOCK | |
120 | #if cond_lock == 0 | |
121 | xaddl %eax, (%ebx) | |
122 | #else | |
123 | xaddl %eax, cond_lock(%ebx) | |
124 | #endif | |
125 | testl %eax, %eax | |
126 | jne 1f | |
127 | ||
128 | /* Unlock the mutex. */ | |
129 | 2: pushl 20(%esp) | |
08c765fa | 130 | .Lpush4: |
1d087a7e UD |
131 | call __pthread_mutex_unlock_internal |
132 | ||
a7720b5e UD |
133 | testl %eax, %eax |
134 | jne 12f | |
135 | ||
1d087a7e UD |
136 | addl $1, total_seq(%ebx) |
137 | adcl $0, total_seq+4(%ebx) | |
138 | ||
139 | /* Install cancellation handler. */ | |
140 | #ifdef PIC | |
141 | call __i686.get_pc_thunk.cx | |
142 | addl $_GLOBAL_OFFSET_TABLE_, %ecx | |
143 | leal __condvar_cleanup@GOTOFF(%ecx), %eax | |
144 | #else | |
145 | leal __condvar_cleanup, %eax | |
146 | #endif | |
a7720b5e | 147 | subl $32, %esp |
08c765fa | 148 | .Lsubl: |
a7720b5e UD |
149 | leal 20(%esp), %edx |
150 | movl %esp, 8(%esp) | |
1d087a7e UD |
151 | movl %eax, 4(%esp) |
152 | movl %edx, (%esp) | |
153 | call __pthread_cleanup_push | |
154 | ||
155 | /* Get and store current wakeup_seq value. */ | |
a7720b5e | 156 | movl 56(%esp), %ecx |
1d087a7e UD |
157 | movl wakeup_seq(%ebx), %edi |
158 | movl wakeup_seq+4(%ebx), %edx | |
a7720b5e UD |
159 | movl %edi, 12(%esp) |
160 | movl %edx, 16(%esp) | |
161 | /* Prepare structure passed to cancellation handler. */ | |
ee2af3e8 | 162 | movl %ecx, (%esp) |
a7720b5e | 163 | movl %ebx, 4(%esp) |
1d087a7e UD |
164 | |
165 | /* Unlock. */ | |
166 | 8: LOCK | |
167 | #if cond_lock == 0 | |
ccf1d573 | 168 | subl $1, (%ebx) |
1d087a7e | 169 | #else |
ccf1d573 | 170 | subl $1, cond_lock(%ebx) |
1d087a7e UD |
171 | #endif |
172 | jne 3f | |
173 | ||
ee2af3e8 | 174 | 4: leal 8(%esp), %eax |
32a589b1 | 175 | call __pthread_enable_asynccancel_2 |
1d087a7e UD |
176 | |
177 | movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ | |
178 | movl %edi, %edx | |
11090a99 | 179 | addl $wakeup_seq, %ebx |
1d087a7e UD |
180 | movl $SYS_futex, %eax |
181 | ENTER_KERNEL | |
11090a99 | 182 | subl $wakeup_seq, %ebx |
1d087a7e | 183 | |
ee2af3e8 | 184 | movl 8(%esp), %eax |
1d087a7e UD |
185 | call __pthread_disable_asynccancel |
186 | ||
187 | /* Lock. */ | |
188 | movl $1, %eax | |
189 | LOCK | |
190 | #if cond_lock == 0 | |
191 | xaddl %eax, (%ebx) | |
192 | #else | |
193 | xaddl %eax, cond_lock(%ebx) | |
194 | #endif | |
195 | testl %eax, %eax | |
196 | jne 5f | |
197 | ||
198 | 6: movl woken_seq(%ebx), %eax | |
199 | movl woken_seq+4(%ebx), %ecx | |
200 | ||
201 | movl wakeup_seq(%ebx), %edi | |
202 | movl wakeup_seq+4(%ebx), %edx | |
203 | ||
46a32546 | 204 | cmpl 16(%esp), %edx |
1d087a7e UD |
205 | ja 7f |
206 | jb 8b | |
46a32546 UD |
207 | cmpl 12(%esp), %edi |
208 | jbe 8b | |
1d087a7e UD |
209 | |
210 | 7: cmpl %ecx, %edx | |
211 | ja 9f | |
212 | jb 8b | |
213 | cmp %eax, %edi | |
214 | jna 8b | |
215 | ||
216 | 9: addl $1, woken_seq(%ebx) | |
217 | adcl $0, woken_seq+4(%ebx) | |
218 | ||
219 | LOCK | |
220 | #if cond_lock == 0 | |
ccf1d573 | 221 | subl $1, (%ebx) |
1d087a7e | 222 | #else |
ccf1d573 | 223 | subl $1, cond_lock(%ebx) |
1d087a7e UD |
224 | #endif |
225 | jne 10f | |
226 | ||
227 | /* Remove cancellation handler. */ | |
748bec08 UD |
228 | 11: movl 20+CLEANUP_PREV(%esp), %edx |
229 | movl %edx, %gs:CLEANUP | |
1d087a7e | 230 | |
ee2af3e8 | 231 | /* Trick ahead: (%esp) contains the address of the mutex. */ |
1d087a7e | 232 | call __pthread_mutex_lock_internal |
ee2af3e8 | 233 | addl $36, %esp |
08c765fa | 234 | .Laddl: |
1d087a7e | 235 | |
a7720b5e | 236 | 14: popl %ebx |
08c765fa | 237 | .Lpop_ebx: |
1d087a7e | 238 | popl %esi |
08c765fa | 239 | .Lpop_esi: |
1d087a7e | 240 | popl %edi |
08c765fa | 241 | .Lpop_edi: |
1d087a7e UD |
242 | |
243 | /* We return the result of the mutex_lock operation. */ | |
244 | ret | |
245 | ||
246 | /* Initial locking failed. */ | |
247 | 1: | |
08c765fa | 248 | .LSbl1: |
1d087a7e UD |
249 | #if cond_lock == 0 |
250 | movl %ebx, %ecx | |
251 | #else | |
252 | leal cond_lock(%ebx), %ecx | |
253 | #endif | |
254 | call __lll_mutex_lock_wait | |
255 | jmp 2b | |
256 | ||
257 | /* Unlock in loop requires waekup. */ | |
258 | 3: | |
08c765fa | 259 | .LSbl2: |
1d087a7e UD |
260 | #if cond_lock == 0 |
261 | movl %ebx, %eax | |
262 | #else | |
263 | leal cond_lock(%ebx), %eax | |
264 | #endif | |
265 | call __lll_mutex_unlock_wake | |
266 | jmp 4b | |
267 | ||
268 | /* Locking in loop failed. */ | |
269 | 5: | |
270 | #if cond_lock == 0 | |
271 | movl %ebx, %ecx | |
272 | #else | |
273 | leal cond_lock(%ebx), %ecx | |
274 | #endif | |
275 | call __lll_mutex_lock_wait | |
276 | jmp 6b | |
277 | ||
a7720b5e | 278 | /* Unlock after loop requires wakeup. */ |
1d087a7e UD |
279 | 10: |
280 | #if cond_lock == 0 | |
281 | movl %ebx, %eax | |
282 | #else | |
283 | leal cond_lock(%ebx), %eax | |
284 | #endif | |
285 | call __lll_mutex_unlock_wake | |
286 | jmp 11b | |
a7720b5e UD |
287 | |
288 | /* The initial unlocking of the mutex failed. */ | |
08c765fa UD |
289 | 12: |
290 | .LSbl3: | |
291 | movl %eax, (%esp) | |
a7720b5e UD |
292 | LOCK |
293 | #if cond_lock == 0 | |
ccf1d573 | 294 | subl $1, (%ebx) |
a7720b5e | 295 | #else |
ccf1d573 | 296 | subl $1, cond_lock(%ebx) |
a7720b5e UD |
297 | #endif |
298 | jne 13f | |
299 | ||
300 | #if cond_lock == 0 | |
301 | movl %ebx, %eax | |
302 | #else | |
303 | leal cond_lock(%ebx), %eax | |
304 | #endif | |
305 | call __lll_mutex_unlock_wake | |
306 | ||
307 | 13: popl %eax | |
308 | jmp 14b | |
08c765fa | 309 | .LENDCODE: |
1d087a7e UD |
310 | .size __pthread_cond_wait, .-__pthread_cond_wait |
311 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | |
312 | GLIBC_2_3_2) | |
313 | ||
314 | ||
08c765fa UD |
315 | .section .eh_frame,"a",@progbits |
316 | .LSTARTFRAME: | |
317 | .long L(ENDCIE)-L(STARTCIE) # Length of the CIE. | |
318 | .LSTARTCIE: | |
319 | .long 0 # CIE ID. | |
320 | .byte 1 # Version number. | |
321 | #ifdef SHARED | |
322 | .string "zR" # NUL-terminated augmentation string. | |
323 | #else | |
324 | .ascii "\0" # NUL-terminated augmentation string. | |
325 | #endif | |
326 | .uleb128 1 # Code alignment factor. | |
327 | .sleb128 -4 # Data alignment factor. | |
328 | .byte 8 # Return address register column. | |
329 | #ifdef SHARED | |
330 | .uleb128 1 # Augmentation value length. | |
331 | .byte 0x1b # Encoding: DW_EH_PE_pcrel | |
332 | # + DW_EH_PE_sdata4. | |
333 | #endif | |
334 | .byte 0x0c # DW_CFA_def_cfa | |
335 | .uleb128 4 | |
336 | .uleb128 4 | |
337 | .byte 0x88 # DW_CFA_offset, column 0x8 | |
338 | .uleb128 1 | |
339 | .align 4 | |
340 | .LENDCIE: | |
341 | ||
342 | .long .LENDFDE-.LSTARTFDE # Length of the FDE. | |
343 | .LSTARTFDE: | |
344 | .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. | |
345 | #ifdef SHARED | |
346 | .long .LSTARTCODE-. # PC-relative start address of the code | |
347 | #else | |
348 | .long .LSTARTCODE # Start address of the code. | |
349 | #endif | |
350 | .long .LENDCODE-.LSTARTCODE # Length of the code. | |
ad2be852 | 351 | #ifdef SHARED |
08c765fa | 352 | .uleb128 0 # No augmentation data. |
ad2be852 | 353 | #endif |
08c765fa UD |
354 | .byte 4 # DW_CFA_advance_loc4 |
355 | .long .Lpush_edi-.LSTARTCODE | |
356 | .byte 14 # DW_CFA_def_cfa_offset | |
357 | .uleb128 8 | |
358 | .byte 4 # DW_CFA_advance_loc4 | |
359 | .long .Lpush_esi-.Lpush_edi | |
360 | .byte 14 # DW_CFA_def_cfa_offset | |
361 | .uleb128 12 | |
362 | .byte 4 # DW_CFA_advance_loc4 | |
363 | .long .Lpush_ebx-.Lpush_esi | |
364 | .byte 14 # DW_CFA_def_cfa_offset | |
365 | .uleb128 16 | |
366 | .byte 4 # DW_CFA_advance_loc4 | |
367 | .long .Lpush4-.Lpush_ebx | |
368 | .byte 14 # DW_CFA_def_cfa_offset | |
369 | .uleb128 20 | |
370 | .byte 4 # DW_CFA_advance_loc4 | |
371 | .long .Lsubl-.Lpush4 | |
372 | .byte 14 # DW_CFA_def_cfa_offset | |
373 | .uleb128 52 | |
374 | .byte 4 # DW_CFA_advance_loc4 | |
375 | .long .Laddl-.Lsubl | |
376 | .byte 14 # DW_CFA_def_cfa_offset | |
377 | .uleb128 16 | |
378 | .byte 4 # DW_CFA_advance_loc4 | |
379 | .long .Lpop_ebx-.Laddl | |
380 | .byte 14 # DW_CFA_def_cfa_offset | |
381 | .uleb128 12 | |
382 | .byte 4 # DW_CFA_advance_loc4 | |
383 | .long .Lpop_esi-.Lpop_ebx | |
384 | .byte 14 # DW_CFA_def_cfa_offset | |
385 | .uleb128 8 | |
386 | .byte 4 # DW_CFA_advance_loc4 | |
387 | .long .Lpop_edi-.Lpop_esi | |
388 | .byte 14 # DW_CFA_def_cfa_offset | |
389 | .uleb128 4 | |
390 | .byte 4 # DW_CFA_advance_loc4 | |
391 | .long .LSbl1-.Lpop_edi | |
392 | .byte 14 # DW_CFA_def_cfa_offset | |
393 | .uleb128 16 | |
394 | .byte 4 # DW_CFA_advance_loc4 | |
395 | .long .LSbl2-.LSbl1 | |
396 | .byte 14 # DW_CFA_def_cfa_offset | |
397 | .uleb128 52 | |
398 | .byte 4 # DW_CFA_advance_loc4 | |
399 | .long .LSbl3-.LSbl2 | |
400 | .byte 14 # DW_CFA_def_cfa_offset | |
401 | .uleb128 20 | |
402 | .align 4 | |
403 | .LENDFDE: | |
404 | ||
405 | ||
1d087a7e UD |
406 | #ifdef PIC |
407 | .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits | |
408 | .globl __i686.get_pc_thunk.cx | |
409 | .hidden __i686.get_pc_thunk.cx | |
410 | .type __i686.get_pc_thunk.cx,@function | |
411 | __i686.get_pc_thunk.cx: | |
412 | movl (%esp), %ecx; | |
413 | ret | |
414 | .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx | |
415 | #endif |