]> git.ipfire.org Git - thirdparty/glibc.git/blob - nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
Update.
[thirdparty/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_timedwait.S
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>
23 #include <pthread-errnos.h>
24
25 #ifdef UP
26 # define LOCK
27 #else
28 # define LOCK lock
29 #endif
30
31 #define SYS_gettimeofday __NR_gettimeofday
32 #define SYS_futex 240
33 #define FUTEX_WAIT 0
34 #define FUTEX_WAKE 1
35
36
37 .text
38
39 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
40 const struct timespec *abstime) */
41 .globl __pthread_cond_timedwait
42 .type __pthread_cond_timedwait, @function
43 .align 16
44 __pthread_cond_timedwait:
45 .LSTARTCODE:
46 pushl %ebp
47 .Lpush_ebp:
48 pushl %edi
49 .Lpush_edi:
50 pushl %esi
51 .Lpush_esi:
52 pushl %ebx
53 .Lpush_ebx:
54
55 movl 20(%esp), %ebx
56 movl 28(%esp), %ebp
57
58 /* Get internal lock. */
59 movl $1, %eax
60 LOCK
61 #if cond_lock == 0
62 xaddl %eax, (%ebx)
63 #else
64 xaddl %eax, cond_lock(%ebx)
65 #endif
66 testl %eax, %eax
67 jne 1f
68
69 /* Store the reference to the mutex. If there is already a
70 different value in there this is a bad user bug. */
71 2: movl 24(%esp), %eax
72 movl %eax, dep_mutex(%ebx)
73
74 /* Unlock the mutex. */
75 xorl %edx, %edx
76 call __pthread_mutex_unlock_usercnt
77
78 testl %eax, %eax
79 jne 16f
80
81 addl $1, total_seq(%ebx)
82 adcl $0, total_seq+4(%ebx)
83
84 subl $20, %esp
85 .Lsubl:
86
87 /* Get and store current wakeup_seq value. */
88 movl wakeup_seq(%ebx), %edi
89 movl wakeup_seq+4(%ebx), %edx
90 movl %edi, 12(%esp)
91 movl %edx, 16(%esp)
92
93 /* Unlock. */
94 8: LOCK
95 #if cond_lock == 0
96 subl $1, (%ebx)
97 #else
98 subl $1, cond_lock(%ebx)
99 #endif
100 jne 3f
101
102 .LcleanupSTART:
103 4: call __pthread_enable_asynccancel
104 movl %eax, (%esp)
105
106 /* Get the current time. */
107 movl %ebx, %edx
108 .LebxmovedUR:
109 #ifdef __NR_clock_gettime
110 /* Get the clock number. Note that the field in the condvar
111 structure stores the number minus 1. */
112 movl cond_clock(%ebx), %ebx
113 /* Only clocks 0 and 1 are allowed. Both are handled in the
114 kernel. */
115 leal 4(%esp), %ecx
116 movl $__NR_clock_gettime, %eax
117 ENTER_KERNEL
118 # ifndef __ASSUME_POSIX_TIMERS
119 cmpl $-ENOSYS, %eax
120 je 19f
121 # endif
122 movl %edx, %ebx
123 .LebxbackUR:
124
125 /* Compute relative timeout. */
126 movl (%ebp), %ecx
127 movl 4(%ebp), %edx
128 subl 4(%esp), %ecx
129 subl 8(%esp), %edx
130 #else
131 /* Get the current time. */
132 leal 4(%esp), %ebx
133 xorl %ecx, %ecx
134 movl $SYS_gettimeofday, %eax
135 ENTER_KERNEL
136 movl %edx, %ebx
137 .LebxbackUR:
138
139 /* Compute relative timeout. */
140 movl 8(%esp), %eax
141 movl $1000, %edx
142 mul %edx /* Milli seconds to nano seconds. */
143 movl (%ebp), %ecx
144 movl 4(%ebp), %edx
145 subl 4(%esp), %ecx
146 subl %eax, %edx
147 #endif
148 jns 12f
149 addl $1000000000, %edx
150 subl $1, %ecx
151 12: testl %ecx, %ecx
152 js 13f
153
154 /* Store relative timeout. */
155 21: movl %ecx, 4(%esp)
156 movl %edx, 8(%esp)
157 leal 4(%esp), %esi
158 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
159 movl %edi, %edx
160 addl $wakeup_seq, %ebx
161 .Ladd_wakeup:
162 movl $SYS_futex, %eax
163 ENTER_KERNEL
164 subl $wakeup_seq, %ebx
165 .Lsub_wakeup:
166 movl %eax, %esi
167
168 movl (%esp), %eax
169 call __pthread_disable_asynccancel
170 .LcleanupEND:
171
172 /* Lock. */
173 movl $1, %eax
174 LOCK
175 #if cond_lock == 0
176 xaddl %eax, (%ebx)
177 #else
178 xaddl %eax, cond_lock(%ebx)
179 #endif
180 testl %eax, %eax
181 jne 5f
182
183 6: movl woken_seq(%ebx), %eax
184 movl woken_seq+4(%ebx), %ecx
185
186 movl wakeup_seq(%ebx), %edi
187 movl wakeup_seq+4(%ebx), %edx
188
189 cmpl 16(%esp), %edx
190 ja 7f
191 jb 15f
192 cmpl 12(%esp), %edi
193 jbe 15f
194
195 7: cmpl %ecx, %edx
196 ja 9f
197 jb 15f
198 cmp %eax, %edi
199 ja 9f
200
201 15: cmpl $-ETIMEDOUT, %esi
202 jne 8b
203
204 13: addl $1, wakeup_seq(%ebx)
205 adcl $0, wakeup_seq+4(%ebx)
206 movl $ETIMEDOUT, %esi
207 jmp 14f
208
209 9: xorl %esi, %esi
210 14: addl $1, woken_seq(%ebx)
211 adcl $0, woken_seq+4(%ebx)
212
213 LOCK
214 #if cond_lock == 0
215 subl $1, (%ebx)
216 #else
217 subl $1, cond_lock(%ebx)
218 #endif
219 jne 10f
220
221 /* Remove cancellation handler. */
222 11: movl 44(%esp), %eax
223 call __pthread_mutex_cond_lock
224 addl $20, %esp
225 .Laddl:
226
227 /* We return the result of the mutex_lock operation if it failed. */
228 testl %eax, %eax
229 cmovel %esi, %eax
230
231 18: popl %ebx
232 .Lpop_ebx:
233 popl %esi
234 .Lpop_esi:
235 popl %edi
236 .Lpop_edi:
237 popl %ebp
238 .Lpop_ebp:
239
240 ret
241
242 /* Initial locking failed. */
243 1:
244 .LSbl1:
245 #if cond_lock == 0
246 movl %ebx, %ecx
247 #else
248 leal cond_lock(%ebx), %ecx
249 #endif
250 call __lll_mutex_lock_wait
251 jmp 2b
252
253 /* Unlock in loop requires waekup. */
254 3:
255 .LSbl2:
256 #if cond_lock == 0
257 movl %ebx, %eax
258 #else
259 leal cond_lock(%ebx), %eax
260 #endif
261 call __lll_mutex_unlock_wake
262 jmp 4b
263
264 /* Locking in loop failed. */
265 5:
266 #if cond_lock == 0
267 movl %ebx, %ecx
268 #else
269 leal cond_lock(%ebx), %ecx
270 #endif
271 call __lll_mutex_lock_wait
272 jmp 6b
273
274 /* Unlock after loop requires waekup. */
275 10:
276 #if cond_lock == 0
277 movl %ebx, %eax
278 #else
279 leal cond_lock(%ebx), %eax
280 #endif
281 call __lll_mutex_unlock_wake
282 jmp 11b
283
284 /* The initial unlocking of the mutex failed. */
285 16:
286 .LSbl3:
287 LOCK
288 #if cond_lock == 0
289 subl $1, (%ebx)
290 #else
291 subl $1, cond_lock(%ebx)
292 #endif
293 jne 18b
294
295 movl %eax, %esi
296 #if cond_lock == 0
297 movl %ebx, %eax
298 #else
299 leal cond_lock(%ebx), %eax
300 #endif
301 call __lll_mutex_unlock_wake
302
303 movl %esi, %eax
304 jmp 18b
305
306 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
307 /* clock_gettime not available. */
308 .LSbl4:
309 19: leal 4(%esp), %ebx
310 xorl %ecx, %ecx
311 movl $SYS_gettimeofday, %eax
312 ENTER_KERNEL
313 movl %edx, %ebx
314
315 /* Compute relative timeout. */
316 movl 8(%esp), %eax
317 movl $1000, %edx
318 mul %edx /* Milli seconds to nano seconds. */
319 movl (%ebp), %ecx
320 movl 4(%ebp), %edx
321 subl 4(%esp), %ecx
322 subl %eax, %edx
323 jns 20f
324 addl $1000000000, %edx
325 subl $1, %ecx
326 20: testl %ecx, %ecx
327 js 13b
328 jmp 21b
329 #endif
330 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
331 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
332 GLIBC_2_3_2)
333
334
335 .type __condvar_tw_cleanup3, @function
336 __condvar_tw_cleanup3:
337 movl 40(%esp), %ebx
338 .LSbl5:
339 jmp __condvar_tw_cleanup
340 .size __condvar_tw_cleanup3, .-__condvar_tw_cleanup3
341 .type __condvar_tw_cleanup2, @function
342 __condvar_tw_cleanup2:
343 subl $wakeup_seq, %ebx
344 .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
345 .type __condvar_tw_cleanup, @function
346 __condvar_tw_cleanup:
347 movl %eax, %esi
348
349 /* Get internal lock. */
350 movl $1, %eax
351 LOCK
352 #if cond_lock == 0
353 xaddl %eax, (%ebx)
354 #else
355 xaddl %eax, cond_lock(%ebx)
356 #endif
357 testl %eax, %eax
358 je 1f
359
360 #if cond_lock == 0
361 movl %ebx, %ecx
362 #else
363 leal cond_lock(%ebx), %ecx
364 #endif
365 call __lll_mutex_lock_wait
366
367 1: addl $1, wakeup_seq(%ebx)
368 adcl $0, wakeup_seq+4(%ebx)
369
370 addl $1, woken_seq(%ebx)
371 adcl $0, woken_seq+4(%ebx)
372
373 LOCK
374 subl $1, cond_lock(%ebx)
375 je 2f
376
377 #if cond_lock == 0
378 movl %ebx, %eax
379 #else
380 leal cond_lock(%ebx), %eax
381 #endif
382 call __lll_mutex_unlock_wake
383
384 /* Wake up all waiters to make sure no signal gets lost. */
385 2: addl $wakeup_seq, %ebx
386 movl $FUTEX_WAKE, %ecx
387 movl $SYS_futex, %eax
388 movl $0x7fffffff, %edx
389 ENTER_KERNEL
390
391 movl 44(%esp), %eax
392 call __pthread_mutex_cond_lock
393
394 movl %esi, (%esp)
395 .LcallUR:
396 call _Unwind_Resume
397 hlt
398 .LENDCODE:
399 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
400
401
402 .section .gcc_except_table,"a",@progbits
403 .LexceptSTART:
404 .byte 0xff # @LPStart format (omit)
405 .byte 0xff # @TType format (omit)
406 .byte 0x0b # call-site format
407 # DW_EH_PE_sdata4
408 .uleb128 .Lcstend-.Lcstbegin
409 .Lcstbegin:
410 .long .LcleanupSTART-.LSTARTCODE
411 .long .Ladd_wakeup-.LcleanupSTART
412 .long __condvar_tw_cleanup-.LSTARTCODE
413 .uleb128 0
414 .long .LebxmovedUR-.LSTARTCODE
415 .long .LebxbackUR-.LebxmovedUR
416 .long __condvar_tw_cleanup3-.LSTARTCODE
417 .uleb128 0
418 .long .LebxmovedUR-.LSTARTCODE
419 .long .Ladd_wakeup-.LebxmovedUR
420 .long __condvar_tw_cleanup-.LSTARTCODE
421 .uleb128 0
422 .long .Ladd_wakeup-.LSTARTCODE
423 .long .Lsub_wakeup-.Ladd_wakeup
424 .long __condvar_tw_cleanup2-.LSTARTCODE
425 .uleb128 0
426 .long .Lsub_wakeup-.LSTARTCODE
427 .long .LcleanupEND-.Lsub_wakeup
428 .long __condvar_tw_cleanup-.LSTARTCODE
429 .uleb128 0
430 .long .LcallUR-.LSTARTCODE
431 .long .LENDCODE-.LcallUR
432 .long 0
433 .uleb128 0
434 .Lcstend:
435
436
437 .section .eh_frame,"a",@progbits
438 .LSTARTFRAME:
439 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
440 .LSTARTCIE:
441 .long 0 # CIE ID.
442 .byte 1 # Version number.
443 #ifdef SHARED
444 .string "zPLR" # NUL-terminated augmentation
445 # string.
446 #else
447 .string "zPL" # NUL-terminated augmentation
448 # string.
449 #endif
450 .uleb128 1 # Code alignment factor.
451 .sleb128 -4 # Data alignment factor.
452 .byte 8 # Return address register
453 # column.
454 #ifdef SHARED
455 .uleb128 7 # Augmentation value length.
456 .byte 0x9b # Personality: DW_EH_PE_pcrel
457 # + DW_EH_PE_sdata4
458 # + DW_EH_PE_indirect
459 .long DW.ref.__gcc_personality_v0-.
460 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
461 # + DW_EH_PE_sdata4.
462 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
463 # + DW_EH_PE_sdata4.
464 #else
465 .uleb128 6 # Augmentation value length.
466 .byte 0x0 # Personality: absolute
467 .long __gcc_personality_v0
468 .byte 0x0 # LSDA Encoding: absolute
469 #endif
470 .byte 0x0c # DW_CFA_def_cfa
471 .uleb128 4
472 .uleb128 4
473 .byte 0x88 # DW_CFA_offset, column 0x8
474 .uleb128 1
475 .align 4
476 .LENDCIE:
477
478 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
479 .LSTARTFDE:
480 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
481 #ifdef SHARED
482 .long .LSTARTCODE-. # PC-relative start address
483 # of the code
484 #else
485 .long .LSTARTCODE # Start address of the code.
486 #endif
487 .long .LENDCODE-.LSTARTCODE # Length of the code.
488 .uleb128 4 # Augmentation size
489 #ifdef SHARED
490 .long .LexceptSTART-.
491 #else
492 .long .LexceptSTART
493 #endif
494 .byte 0x40+.Lpush_ebp-.LSTARTCODE # DW_CFA_advance_loc+N
495 .byte 14 # DW_CFA_def_cfa_offset
496 .uleb128 8
497 .byte 0x85 # DW_CFA_offset %ebp
498 .uleb128 2
499 .byte 0x40+ .Lpush_edi-.Lpush_ebp # DW_CFA_advance_loc+N
500 .byte 14 # DW_CFA_def_cfa_offset
501 .uleb128 12
502 .byte 0x87 # DW_CFA_offset %edi
503 .uleb128 3
504 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
505 .byte 14 # DW_CFA_def_cfa_offset
506 .uleb128 16
507 .byte 0x86 # DW_CFA_offset %esi
508 .uleb128 4
509 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
510 .byte 14 # DW_CFA_def_cfa_offset
511 .uleb128 20
512 .byte 0x83 # DW_CFA_offset %ebx
513 .uleb128 5
514 .byte 2 # DW_CFA_advance_loc1
515 .byte .Lsubl-.Lpush_ebx
516 .byte 14 # DW_CFA_def_cfa_offset
517 .uleb128 40
518 .byte 3 # DW_CFA_advance_loc2
519 .2byte .Laddl-.Lsubl
520 .byte 14 # DW_CFA_def_cfa_offset
521 .uleb128 20
522 .byte 0x40+.Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
523 .byte 14 # DW_CFA_def_cfa_offset
524 .uleb128 16
525 .byte 0xc3 # DW_CFA_restore %ebx
526 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
527 .byte 14 # DW_CFA_def_cfa_offset
528 .uleb128 12
529 .byte 0xc6 # DW_CFA_restore %esi
530 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
531 .byte 14 # DW_CFA_def_cfa_offset
532 .uleb128 8
533 .byte 0xc7 # DW_CFA_restore %edi
534 .byte 0x40+.Lpop_ebp-.Lpop_edi # DW_CFA_advance_loc+N
535 .byte 14 # DW_CFA_def_cfa_offset
536 .uleb128 4
537 .byte 0xc5 # DW_CFA_restore %ebp
538 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
539 .byte 14 # DW_CFA_def_cfa_offset
540 .uleb128 20
541 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
542 .byte 14 # DW_CFA_def_cfa_offset
543 .uleb128 64
544 .byte 0x85 # DW_CFA_offset %ebp
545 .uleb128 2
546 .byte 0x87 # DW_CFA_offset %edi
547 .uleb128 3
548 .byte 0x86 # DW_CFA_offset %esi
549 .uleb128 4
550 .byte 0x83 # DW_CFA_offset %ebx
551 .uleb128 5
552 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
553 .byte 14 # DW_CFA_def_cfa_offset
554 .uleb128 24
555 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
556 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
557 .byte 14 # DW_CFA_def_cfa_offset
558 .uleb128 64
559 .byte 4 # DW_CFA_advance_loc4
560 .long .LSbl5-.LSbl4
561 #else
562 .byte 4 # DW_CFA_advance_loc4
563 .long .LSbl5-.LSbl3
564 #endif
565 .byte 14 # DW_CFA_def_cfa_offset
566 .uleb128 40
567 .align 4
568 .LENDFDE:
569
570 #ifdef SHARED
571 .hidden DW.ref.__gcc_personality_v0
572 .weak DW.ref.__gcc_personality_v0
573 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
574 .align 4
575 .type DW.ref.__gcc_personality_v0, @object
576 .size DW.ref.__gcc_personality_v0, 4
577 DW.ref.__gcc_personality_v0:
578 .long __gcc_personality_v0
579 #endif