[BZ #163]
[platform/upstream/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_wait.S
1 /* Copyright (C) 2002, 2003, 2004 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 <tcb-offsets.h>
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 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
39         .globl  __pthread_cond_wait
40         .type   __pthread_cond_wait, @function
41         .align  16
42 __pthread_cond_wait:
43 .LSTARTCODE:
44
45         pushl   %edi
46 .Lpush_edi:
47         pushl   %esi
48 .Lpush_esi:
49         pushl   %ebx
50 .Lpush_ebx:
51
52         xorl    %esi, %esi
53         movl    16(%esp), %ebx
54
55         /* Get internal lock.  */
56         movl    $1, %edx
57         xorl    %eax, %eax
58         LOCK
59 #if cond_lock == 0
60         cmpxchgl %edx, (%ebx)
61 #else
62         cmpxchgl %edx, cond_lock(%ebx)
63 #endif
64         jnz     1f
65
66         /* Store the reference to the mutex.  If there is already a
67            different value in there this is a bad user bug.  */
68 2:      cmpl    $-1, dep_mutex(%ebx)
69         movl    20(%esp), %eax
70         je      15f
71         movl    %eax, dep_mutex(%ebx)
72
73         /* Unlock the mutex.  */
74 15:     xorl    %edx, %edx
75         call    __pthread_mutex_unlock_usercnt
76
77         testl   %eax, %eax
78         jne     12f
79
80         addl    $1, total_seq(%ebx)
81         adcl    $0, total_seq+4(%ebx)
82
83 #define FRAME_SIZE 16
84         subl    $FRAME_SIZE, %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    broadcast_seq(%ebx), %eax
91         movl    %edi, 4(%esp)
92         movl    %edx, 8(%esp)
93         movl    %eax, 12(%esp)
94
95         /* Unlock.  */
96 8:      LOCK
97 #if cond_lock == 0
98         subl    $1, (%ebx)
99 #else
100         subl    $1, cond_lock(%ebx)
101 #endif
102         jne     3f
103
104 .LcleanupSTART:
105 4:      call    __pthread_enable_asynccancel
106         movl    %eax, (%esp)
107
108         movl    %esi, %ecx      /* movl $FUTEX_WAIT, %ecx */
109         movl    %edi, %edx
110         addl    $wakeup_seq, %ebx
111 .Ladd_wakeup:
112         movl    $SYS_futex, %eax
113         ENTER_KERNEL
114         subl    $wakeup_seq, %ebx
115 .Lsub_wakeup:
116
117         movl    (%esp), %eax
118         call    __pthread_disable_asynccancel
119 .LcleanupEND:
120
121         /* Lock.  */
122         movl    $1, %edx
123         xorl    %eax, %eax
124         LOCK
125 #if cond_lock == 0
126         cmpxchgl %edx, (%ebx)
127 #else
128         cmpxchgl %edx, cond_lock(%ebx)
129 #endif
130         jnz     5f
131
132 6:      movl    broadcast_seq(%ebx), %eax
133         cmpl    12(%esp), %eax
134         jne     16f
135
136         movl    woken_seq(%ebx), %eax
137         movl    woken_seq+4(%ebx), %ecx
138
139         movl    wakeup_seq(%ebx), %edi
140         movl    wakeup_seq+4(%ebx), %edx
141
142         cmpl    8(%esp), %edx
143         jne     7f
144         cmpl    4(%esp), %edi
145         je      8b
146
147 7:      cmpl    %ecx, %edx
148         jne     9f
149         cmp     %eax, %edi
150         je      8b
151
152 9:      addl    $1, woken_seq(%ebx)
153         adcl    $0, woken_seq+4(%ebx)
154
155         /* Unlock */
156 16:     LOCK
157 #if cond_lock == 0
158         subl    $1, (%ebx)
159 #else
160         subl    $1, cond_lock(%ebx)
161 #endif
162         jne     10f
163
164 11:     movl    20+FRAME_SIZE(%esp), %eax
165         call    __pthread_mutex_cond_lock
166         addl    $FRAME_SIZE, %esp
167 .Laddl:
168
169 14:     popl    %ebx
170 .Lpop_ebx:
171         popl    %esi
172 .Lpop_esi:
173         popl    %edi
174 .Lpop_edi:
175
176         /* We return the result of the mutex_lock operation.  */
177         ret
178
179         /* Initial locking failed.  */
180 1:
181 .LSbl1:
182 #if cond_lock == 0
183         movl    %ebx, %ecx
184 #else
185         leal    cond_lock(%ebx), %ecx
186 #endif
187         call    __lll_mutex_lock_wait
188         jmp     2b
189
190         /* Unlock in loop requires waekup.  */
191 3:
192 .LSbl2:
193 #if cond_lock == 0
194         movl    %ebx, %eax
195 #else
196         leal    cond_lock(%ebx), %eax
197 #endif
198         call    __lll_mutex_unlock_wake
199         jmp     4b
200
201         /* Locking in loop failed.  */
202 5:
203 #if cond_lock == 0
204         movl    %ebx, %ecx
205 #else
206         leal    cond_lock(%ebx), %ecx
207 #endif
208         call    __lll_mutex_lock_wait
209         jmp     6b
210
211         /* Unlock after loop requires wakeup.  */
212 10:
213 #if cond_lock == 0
214         movl    %ebx, %eax
215 #else
216         leal    cond_lock(%ebx), %eax
217 #endif
218         call    __lll_mutex_unlock_wake
219         jmp     11b
220
221         /* The initial unlocking of the mutex failed.  */
222 12:
223 .LSbl3:
224         LOCK
225 #if cond_lock == 0
226         subl    $1, (%ebx)
227 #else
228         subl    $1, cond_lock(%ebx)
229 #endif
230         jne     14b
231
232         movl    %eax, %esi
233 #if cond_lock == 0
234         movl    %ebx, %eax
235 #else
236         leal    cond_lock(%ebx), %eax
237 #endif
238         call    __lll_mutex_unlock_wake
239
240         movl    %esi, %eax
241         jmp     14b
242         .size   __pthread_cond_wait, .-__pthread_cond_wait
243 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
244                   GLIBC_2_3_2)
245
246
247         .type   __condvar_w_cleanup2, @function
248 __condvar_w_cleanup2:
249         subl    $wakeup_seq, %ebx
250         .size   __condvar_w_cleanup2, .-__condvar_w_cleanup2
251 .LSbl4:
252         .type   __condvar_w_cleanup, @function
253 __condvar_w_cleanup:
254         movl    %eax, %esi
255
256         /* Get internal lock.  */
257         movl    $1, %edx
258         xorl    %eax, %eax
259         LOCK
260 #if cond_lock == 0
261         cmpxchgl %edx, (%ebx)
262 #else
263         cmpxchgl %edx, cond_lock(%ebx)
264 #endif
265         jz      1f
266
267 #if cond_lock == 0
268         movl    %ebx, %ecx
269 #else
270         leal    cond_lock(%ebx), %ecx
271 #endif
272         call    __lll_mutex_lock_wait
273
274 1:      movl    broadcast_seq(%ebx), %eax
275         cmpl    12(%esp), %eax
276         jne     3f
277
278         addl    $1, wakeup_seq(%ebx)
279         adcl    $0, wakeup_seq+4(%ebx)
280
281         addl    $1, woken_seq(%ebx)
282         adcl    $0, woken_seq+4(%ebx)
283
284 3:      LOCK
285 #if cond_lock == 0
286         subl    $1, (%ebx)
287 #else
288         subl    $1, cond_lock(%ebx)
289 #endif
290         je      2f
291
292 #if cond_lock == 0
293         movl    %ebx, %eax
294 #else
295         leal    cond_lock(%ebx), %eax
296 #endif
297         call    __lll_mutex_unlock_wake
298
299         /* Wake up all waiters to make sure no signal gets lost.  */
300 2:      addl    $wakeup_seq, %ebx
301         movl    $FUTEX_WAKE, %ecx
302         movl    $SYS_futex, %eax
303         movl    $0x7fffffff, %edx
304         ENTER_KERNEL
305
306         movl    20+FRAME_SIZE(%esp), %eax
307         call    __pthread_mutex_cond_lock
308
309         movl    %esi, (%esp)
310 .LcallUR:
311         call    _Unwind_Resume
312         hlt
313 .LENDCODE:
314         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
315
316
317         .section .gcc_except_table,"a",@progbits
318 .LexceptSTART:
319         .byte   0xff                            # @LPStart format (omit)
320         .byte   0xff                            # @TType format (omit)
321         .byte   0x0b                            # call-site format
322                                                 # DW_EH_PE_sdata4
323         .uleb128 .Lcstend-.Lcstbegin
324 .Lcstbegin:
325         .long   .LcleanupSTART-.LSTARTCODE
326         .long   .Ladd_wakeup-.LcleanupSTART
327         .long   __condvar_w_cleanup-.LSTARTCODE
328         .uleb128  0
329         .long   .Ladd_wakeup-.LSTARTCODE
330         .long   .Lsub_wakeup-.Ladd_wakeup
331         .long   __condvar_w_cleanup2-.LSTARTCODE
332         .uleb128  0
333         .long   .Lsub_wakeup-.LSTARTCODE
334         .long   .LcleanupEND-.Lsub_wakeup
335         .long   __condvar_w_cleanup-.LSTARTCODE
336         .uleb128  0
337         .long   .LcallUR-.LSTARTCODE
338         .long   .LENDCODE-.LcallUR
339         .long   0
340         .uleb128  0
341 .Lcstend:
342
343         .section .eh_frame,"a",@progbits
344 .LSTARTFRAME:
345         .long   L(ENDCIE)-L(STARTCIE)           # Length of the CIE.
346 .LSTARTCIE:
347         .long   0                               # CIE ID.
348         .byte   1                               # Version number.
349 #ifdef SHARED
350         .string "zPLR"                          # NUL-terminated augmentation
351                                                 # string.
352 #else
353         .string "zPL"                           # NUL-terminated augmentation
354                                                 # string.
355 #endif
356         .uleb128 1                              # Code alignment factor.
357         .sleb128 -4                             # Data alignment factor.
358         .byte   8                               # Return address register
359                                                 # column.
360 #ifdef SHARED
361         .uleb128 7                              # Augmentation value length.
362         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
363                                                 # + DW_EH_PE_sdata4
364                                                 # + DW_EH_PE_indirect
365         .long   DW.ref.__gcc_personality_v0-.
366         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
367                                                 # + DW_EH_PE_sdata4.
368         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
369                                                 # + DW_EH_PE_sdata4.
370 #else
371         .uleb128 6                              # Augmentation value length.
372         .byte   0x0                             # Personality: absolute
373         .long   __gcc_personality_v0
374         .byte   0x0                             # LSDA Encoding: absolute
375 #endif
376         .byte 0x0c                              # DW_CFA_def_cfa
377         .uleb128 4
378         .uleb128 4
379         .byte   0x88                            # DW_CFA_offset, column 0x8
380         .uleb128 1
381         .align 4
382 .LENDCIE:
383
384         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
385 .LSTARTFDE:
386         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
387 #ifdef SHARED
388         .long   .LSTARTCODE-.                   # PC-relative start address
389                                                 # of the code.
390 #else
391         .long   .LSTARTCODE                     # Start address of the code.
392 #endif
393         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
394         .uleb128 4                              # Augmentation size
395 #ifdef SHARED
396         .long   .LexceptSTART-.
397 #else
398         .long   .LexceptSTART
399 #endif
400         .byte   0x40+.Lpush_edi-.LSTARTCODE     # DW_CFA_advance_loc+N
401         .byte   14                              # DW_CFA_def_cfa_offset
402         .uleb128 8
403         .byte   0x87                            # DW_CFA_offset %edi
404         .uleb128 2
405         .byte   0x40+.Lpush_esi-.Lpush_edi      # DW_CFA_advance_loc+N
406         .byte   14                              # DW_CFA_def_cfa_offset
407         .uleb128 12
408         .byte   0x86                            # DW_CFA_offset %esi
409         .uleb128 3
410         .byte   0x40+.Lpush_ebx-.Lpush_esi      # DW_CFA_advance_loc+N
411         .byte   14                              # DW_CFA_def_cfa_offset
412         .uleb128 16
413         .byte   0x83                            # DW_CFA_offset %ebx
414         .uleb128 4
415         .byte   2                               # DW_CFA_advance_loc1
416         .byte   .Lsubl-.Lpush_ebx
417         .byte   14                              # DW_CFA_def_cfa_offset
418         .uleb128 16+FRAME_SIZE
419         .byte   2                               # DW_CFA_advance_loc1
420         .byte   .Laddl-.Lsubl
421         .byte   14                              # DW_CFA_def_cfa_offset
422         .uleb128 16
423         .byte   0x40+ .Lpop_ebx-.Laddl          # DW_CFA_advance_loc+N
424         .byte   14                              # DW_CFA_def_cfa_offset
425         .uleb128 12
426         .byte   0xc3                            # DW_CFA_restore %ebx
427         .byte   0x40+.Lpop_esi-.Lpop_ebx        # DW_CFA_advance_loc+N
428         .byte   14                              # DW_CFA_def_cfa_offset
429         .uleb128 8
430         .byte   0xc6                            # DW_CFA_restore %esi
431         .byte   0x40+.Lpop_edi-.Lpop_esi        # DW_CFA_advance_loc+N
432         .byte   14                              # DW_CFA_def_cfa_offset
433         .uleb128 4
434         .byte   0xc7                            # DW_CFA_restore %edi
435         .byte   0x40+.LSbl1-.Lpop_edi           # DW_CFA_advance_loc+N
436         .byte   14                              # DW_CFA_def_cfa_offset
437         .uleb128 16
438         .byte   0x87                            # DW_CFA_offset %edi
439         .uleb128 2
440         .byte   0x86                            # DW_CFA_offset %esi
441         .uleb128 3
442         .byte   0x83                            # DW_CFA_offset %ebx
443         .uleb128 4
444         .byte   0x40+.LSbl2-.LSbl1              # DW_CFA_advance_loc+N
445         .byte   14                              # DW_CFA_def_cfa_offset
446         .uleb128 16+FRAME_SIZE
447         .byte   0x40+.LSbl3-.LSbl2              # DW_CFA_advance_loc+N
448         .byte   14                              # DW_CFA_def_cfa_offset
449         .uleb128 16
450         .byte   0x40+.LSbl4-.LSbl3              # DW_CFA_advance_loc+N
451         .byte   14                              # DW_CFA_def_cfa_offset
452         .uleb128 16+FRAME_SIZE
453         .align  4
454 .LENDFDE:
455
456
457 #ifdef PIC
458         .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
459         .globl  __i686.get_pc_thunk.cx
460         .hidden __i686.get_pc_thunk.cx
461         .type   __i686.get_pc_thunk.cx,@function
462 __i686.get_pc_thunk.cx:
463         movl (%esp), %ecx;
464         ret
465         .size   __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
466 #endif
467
468 #ifdef SHARED
469         .hidden DW.ref.__gcc_personality_v0
470         .weak   DW.ref.__gcc_personality_v0
471         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
472         .align 4
473         .type   DW.ref.__gcc_personality_v0, @object
474         .size   DW.ref.__gcc_personality_v0, 4
475 DW.ref.__gcc_personality_v0:
476         .long   __gcc_personality_v0
477 #endif