Fix pthread_cond_*wait with requeue-PI on i386.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_timedwait.S
blobdee73f0c321523fa2dbfbd6a8dd688b27b6bf654
1 /* Copyright (C) 2002-2004,2006-2007,2009,2010 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
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.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <pthread-errnos.h>
25 #include <pthread-pi-defines.h>
26 #include <kernel-features.h>
29         .text
31 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
32                                const struct timespec *abstime)  */
33         .globl  __pthread_cond_timedwait
34         .type   __pthread_cond_timedwait, @function
35         .align  16
36 __pthread_cond_timedwait:
37 .LSTARTCODE:
38         cfi_startproc
39 #ifdef SHARED
40         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
41                         DW.ref.__gcc_personality_v0)
42         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
43 #else
44         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
45         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
46 #endif
48         pushl   %ebp
49         cfi_adjust_cfa_offset(4)
50         cfi_rel_offset(%ebp, 0)
51         pushl   %edi
52         cfi_adjust_cfa_offset(4)
53         cfi_rel_offset(%edi, 0)
54         pushl   %esi
55         cfi_adjust_cfa_offset(4)
56         cfi_rel_offset(%esi, 0)
57         pushl   %ebx
58         cfi_adjust_cfa_offset(4)
59         cfi_rel_offset(%ebx, 0)
61         movl    20(%esp), %ebx
62         movl    28(%esp), %ebp
64         cmpl    $1000000000, 4(%ebp)
65         movl    $EINVAL, %eax
66         jae     18f
68         /* Get internal lock.  */
69         movl    $1, %edx
70         xorl    %eax, %eax
71         LOCK
72 #if cond_lock == 0
73         cmpxchgl %edx, (%ebx)
74 #else
75         cmpxchgl %edx, cond_lock(%ebx)
76 #endif
77         jnz     1f
79         /* Store the reference to the mutex.  If there is already a
80            different value in there this is a bad user bug.  */
81 2:      cmpl    $-1, dep_mutex(%ebx)
82         movl    24(%esp), %eax
83         je      17f
84         movl    %eax, dep_mutex(%ebx)
86         /* Unlock the mutex.  */
87 17:     xorl    %edx, %edx
88         call    __pthread_mutex_unlock_usercnt
90         testl   %eax, %eax
91         jne     16f
93         addl    $1, total_seq(%ebx)
94         adcl    $0, total_seq+4(%ebx)
95         addl    $1, cond_futex(%ebx)
96         addl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
98 #define FRAME_SIZE 32
99         subl    $FRAME_SIZE, %esp
100         cfi_adjust_cfa_offset(FRAME_SIZE)
101         cfi_remember_state
103         /* Get and store current wakeup_seq value.  */
104         movl    wakeup_seq(%ebx), %edi
105         movl    wakeup_seq+4(%ebx), %edx
106         movl    broadcast_seq(%ebx), %eax
107         movl    %edi, 12(%esp)
108         movl    %edx, 16(%esp)
109         movl    %eax, 20(%esp)
111         /* Reset the pi-requeued flag.  */
112 8:      movl    $0, 24(%esp)
113         /* Get the current time.  */
114         movl    %ebx, %edx
115 #ifdef __NR_clock_gettime
116         /* Get the clock number.  */
117         movl    cond_nwaiters(%ebx), %ebx
118         andl    $((1 << nwaiters_shift) - 1), %ebx
119         /* Only clocks 0 and 1 are allowed so far.  Both are handled in the
120            kernel.  */
121         leal    4(%esp), %ecx
122         movl    $__NR_clock_gettime, %eax
123         ENTER_KERNEL
124 # ifndef __ASSUME_POSIX_TIMERS
125         cmpl    $-ENOSYS, %eax
126         je      19f
127 # endif
128         movl    %edx, %ebx
130         /* Compute relative timeout.  */
131         movl    (%ebp), %ecx
132         movl    4(%ebp), %edx
133         subl    4(%esp), %ecx
134         subl    8(%esp), %edx
135 #else
136         /* Get the current time.  */
137         leal    4(%esp), %ebx
138         xorl    %ecx, %ecx
139         movl    $__NR_gettimeofday, %eax
140         ENTER_KERNEL
141         movl    %edx, %ebx
143         /* Compute relative timeout.  */
144         movl    8(%esp), %eax
145         movl    $1000, %edx
146         mul     %edx            /* Milli seconds to nano seconds.  */
147         movl    (%ebp), %ecx
148         movl    4(%ebp), %edx
149         subl    4(%esp), %ecx
150         subl    %eax, %edx
151 #endif
152         jns     12f
153         addl    $1000000000, %edx
154         subl    $1, %ecx
155 12:     testl   %ecx, %ecx
156         movl    $-ETIMEDOUT, %esi
157         js      6f
159         /* Store relative timeout.  */
160 21:     movl    %ecx, 4(%esp)
161         movl    %edx, 8(%esp)
163         movl    cond_futex(%ebx), %edi
164         movl    %edi, 28(%esp)
166         /* Unlock.  */
167         LOCK
168 #if cond_lock == 0
169         subl    $1, (%ebx)
170 #else
171         subl    $1, cond_lock(%ebx)
172 #endif
173         jne     3f
175 .LcleanupSTART:
176 4:      call    __pthread_enable_asynccancel
177         movl    %eax, (%esp)
179 #if FUTEX_PRIVATE_FLAG > 255
180         xorl    %ecx, %ecx
181 #endif
182         cmpl    $-1, dep_mutex(%ebx)
183         sete    %cl
184         je      40f
186         movl    dep_mutex(%ebx), %edi
187         /* Requeue to a non-robust PI mutex if the PI bit is set and
188            the robust bit is not set.  */
189         movl    MUTEX_KIND(%edi), %eax
190         andl    $(ROBUST_BIT|PI_BIT), %eax
191         cmpl    $PI_BIT, %eax
192         jne     40f
194         movl    $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
195         /* The following only works like this because we only support
196            two clocks, represented using a single bit.  */
197         testl   $1, cond_nwaiters(%ebx)
198         /* XXX Need to implement using sete instead of a jump.  */
199         jne     42f
200         orl     $FUTEX_CLOCK_REALTIME, %ecx
202         /* Requeue-PI uses absolute timeout */
203 42:     leal    (%ebp), %esi
204         movl    28(%esp), %edx
205         addl    $cond_futex, %ebx
206         movl    $SYS_futex, %eax
207         ENTER_KERNEL
208         subl    $cond_futex, %ebx
209         movl    %eax, %esi
210         /* Set the pi-requeued flag only if the kernel has returned 0. The
211            kernel does not hold the mutex on ETIMEDOUT or any other error.  */
212         cmpl    $0, %eax
213         sete    24(%esp)
214         je      41f
216         /* Normal and PI futexes dont mix. Use normal futex functions only
217            if the kernel does not support the PI futex functions.  */
218         cmpl    $-ENOSYS, %eax
219         jne     41f
220         xorl    %ecx, %ecx
222 40:     subl    $1, %ecx
223 #ifdef __ASSUME_PRIVATE_FUTEX
224         andl    $FUTEX_PRIVATE_FLAG, %ecx
225 #else
226         andl    %gs:PRIVATE_FUTEX, %ecx
227 #endif
228 #if FUTEX_WAIT != 0
229         addl    $FUTEX_WAIT, %ecx
230 #endif
231         leal    4(%esp), %esi
232         movl    28(%esp), %edx
233         addl    $cond_futex, %ebx
234 .Ladd_cond_futex:
235         movl    $SYS_futex, %eax
236         ENTER_KERNEL
237         subl    $cond_futex, %ebx
238 .Lsub_cond_futex:
239         movl    %eax, %esi
241 41:     movl    (%esp), %eax
242         call    __pthread_disable_asynccancel
243 .LcleanupEND:
245         /* Lock.  */
246         movl    $1, %edx
247         xorl    %eax, %eax
248         LOCK
249 #if cond_lock == 0
250         cmpxchgl %edx, (%ebx)
251 #else
252         cmpxchgl %edx, cond_lock(%ebx)
253 #endif
254         jnz     5f
256 6:      movl    broadcast_seq(%ebx), %eax
257         cmpl    20(%esp), %eax
258         jne     23f
260         movl    woken_seq(%ebx), %eax
261         movl    woken_seq+4(%ebx), %ecx
263         movl    wakeup_seq(%ebx), %edi
264         movl    wakeup_seq+4(%ebx), %edx
266         cmpl    16(%esp), %edx
267         jne     7f
268         cmpl    12(%esp), %edi
269         je      15f
271 7:      cmpl    %ecx, %edx
272         jne     9f
273         cmp     %eax, %edi
274         jne     9f
276 15:     cmpl    $-ETIMEDOUT, %esi
277         jne     8b
279         addl    $1, wakeup_seq(%ebx)
280         adcl    $0, wakeup_seq+4(%ebx)
281         addl    $1, cond_futex(%ebx)
282         movl    $ETIMEDOUT, %esi
283         jmp     14f
285 23:     xorl    %esi, %esi
286         jmp     24f
288 9:      xorl    %esi, %esi
289 14:     addl    $1, woken_seq(%ebx)
290         adcl    $0, woken_seq+4(%ebx)
292 24:     subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
294         /* Wake up a thread which wants to destroy the condvar object.  */
295         movl    total_seq(%ebx), %eax
296         andl    total_seq+4(%ebx), %eax
297         cmpl    $0xffffffff, %eax
298         jne     25f
299         movl    cond_nwaiters(%ebx), %eax
300         andl    $~((1 << nwaiters_shift) - 1), %eax
301         jne     25f
303         addl    $cond_nwaiters, %ebx
304         movl    $SYS_futex, %eax
305 #if FUTEX_PRIVATE_FLAG > 255
306         xorl    %ecx, %ecx
307 #endif
308         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
309         sete    %cl
310         subl    $1, %ecx
311 #ifdef __ASSUME_PRIVATE_FUTEX
312         andl    $FUTEX_PRIVATE_FLAG, %ecx
313 #else
314         andl    %gs:PRIVATE_FUTEX, %ecx
315 #endif
316         addl    $FUTEX_WAKE, %ecx
317         movl    $1, %edx
318         ENTER_KERNEL
319         subl    $cond_nwaiters, %ebx
321 25:     LOCK
322 #if cond_lock == 0
323         subl    $1, (%ebx)
324 #else
325         subl    $1, cond_lock(%ebx)
326 #endif
327         jne     10f
329 11:     movl    24+FRAME_SIZE(%esp), %eax
330         /* With requeue_pi, the mutex lock is held in the kernel.  */
331         movl    24(%esp), %ecx
332         testl   %ecx, %ecx
333         jnz     27f
335         call    __pthread_mutex_cond_lock
336 26:     addl    $FRAME_SIZE, %esp
337         cfi_adjust_cfa_offset(-FRAME_SIZE);
339         /* We return the result of the mutex_lock operation if it failed.  */
340         testl   %eax, %eax
341 #ifdef HAVE_CMOV
342         cmovel  %esi, %eax
343 #else
344         jne     22f
345         movl    %esi, %eax
347 #endif
349 18:     popl    %ebx
350         cfi_adjust_cfa_offset(-4)
351         cfi_restore(%ebx)
352         popl    %esi
353         cfi_adjust_cfa_offset(-4)
354         cfi_restore(%esi)
355         popl    %edi
356         cfi_adjust_cfa_offset(-4)
357         cfi_restore(%edi)
358         popl    %ebp
359         cfi_adjust_cfa_offset(-4)
360         cfi_restore(%ebp)
362         ret
364         cfi_restore_state
366 27:     call    __pthread_mutex_cond_lock_adjust
367         xorl    %eax, %eax
368         jmp     26b
370         cfi_adjust_cfa_offset(-FRAME_SIZE);
371         /* Initial locking failed.  */
373 #if cond_lock == 0
374         movl    %ebx, %edx
375 #else
376         leal    cond_lock(%ebx), %edx
377 #endif
378 #if (LLL_SHARED-LLL_PRIVATE) > 255
379         xorl    %ecx, %ecx
380 #endif
381         cmpl    $-1, dep_mutex(%ebx)
382         setne   %cl
383         subl    $1, %ecx
384         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
385 #if LLL_PRIVATE != 0
386         addl    $LLL_PRIVATE, %ecx
387 #endif
388         call    __lll_lock_wait
389         jmp     2b
391         /* The initial unlocking of the mutex failed.  */
393         LOCK
394 #if cond_lock == 0
395         subl    $1, (%ebx)
396 #else
397         subl    $1, cond_lock(%ebx)
398 #endif
399         jne     18b
401         movl    %eax, %esi
402 #if cond_lock == 0
403         movl    %ebx, %eax
404 #else
405         leal    cond_lock(%ebx), %eax
406 #endif
407 #if (LLL_SHARED-LLL_PRIVATE) > 255
408         xorl    %ecx, %ecx
409 #endif
410         cmpl    $-1, dep_mutex(%ebx)
411         setne   %cl
412         subl    $1, %ecx
413         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
414 #if LLL_PRIVATE != 0
415         addl    $LLL_PRIVATE, %ecx
416 #endif
417         call    __lll_unlock_wake
419         movl    %esi, %eax
420         jmp     18b
422         cfi_adjust_cfa_offset(FRAME_SIZE)
424         /* Unlock in loop requires wakeup.  */
426 #if cond_lock == 0
427         movl    %ebx, %eax
428 #else
429         leal    cond_lock(%ebx), %eax
430 #endif
431 #if (LLL_SHARED-LLL_PRIVATE) > 255
432         xorl    %ecx, %ecx
433 #endif
434         cmpl    $-1, dep_mutex(%ebx)
435         setne   %cl
436         subl    $1, %ecx
437         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
438 #if LLL_PRIVATE != 0
439         addl    $LLL_PRIVATE, %ecx
440 #endif
441         call    __lll_unlock_wake
442         jmp     4b
444         /* Locking in loop failed.  */
446 #if cond_lock == 0
447         movl    %ebx, %edx
448 #else
449         leal    cond_lock(%ebx), %edx
450 #endif
451 #if (LLL_SHARED-LLL_PRIVATE) > 255
452         xorl    %ecx, %ecx
453 #endif
454         cmpl    $-1, dep_mutex(%ebx)
455         setne   %cl
456         subl    $1, %ecx
457         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
458 #if LLL_PRIVATE != 0
459         addl    $LLL_PRIVATE, %ecx
460 #endif
461         call    __lll_lock_wait
462         jmp     6b
464         /* Unlock after loop requires wakeup.  */
466 #if cond_lock == 0
467         movl    %ebx, %eax
468 #else
469         leal    cond_lock(%ebx), %eax
470 #endif
471 #if (LLL_SHARED-LLL_PRIVATE) > 255
472         xorl    %ecx, %ecx
473 #endif
474         cmpl    $-1, dep_mutex(%ebx)
475         setne   %cl
476         subl    $1, %ecx
477         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
478 #if LLL_PRIVATE != 0
479         addl    $LLL_PRIVATE, %ecx
480 #endif
481         call    __lll_unlock_wake
482         jmp     11b
484 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
485         /* clock_gettime not available.  */
486 19:     leal    4(%esp), %ebx
487         xorl    %ecx, %ecx
488         movl    $__NR_gettimeofday, %eax
489         ENTER_KERNEL
490         movl    %edx, %ebx
492         /* Compute relative timeout.  */
493         movl    8(%esp), %eax
494         movl    $1000, %edx
495         mul     %edx            /* Milli seconds to nano seconds.  */
496         movl    (%ebp), %ecx
497         movl    4(%ebp), %edx
498         subl    4(%esp), %ecx
499         subl    %eax, %edx
500         jns     20f
501         addl    $1000000000, %edx
502         subl    $1, %ecx
503 20:     testl   %ecx, %ecx
504         movl    $-ETIMEDOUT, %esi
505         js      6b
506         jmp     21b
507 #endif
508         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
509 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
510                   GLIBC_2_3_2)
513         .type   __condvar_tw_cleanup2, @function
514 __condvar_tw_cleanup2:
515         subl    $cond_futex, %ebx
516         .size   __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
517         .type   __condvar_tw_cleanup, @function
518 __condvar_tw_cleanup:
519         movl    %eax, %esi
521         /* Get internal lock.  */
522         movl    $1, %edx
523         xorl    %eax, %eax
524         LOCK
525 #if cond_lock == 0
526         cmpxchgl %edx, (%ebx)
527 #else
528         cmpxchgl %edx, cond_lock(%ebx)
529 #endif
530         jz      1f
532 #if cond_lock == 0
533         movl    %ebx, %edx
534 #else
535         leal    cond_lock(%ebx), %edx
536 #endif
537 #if (LLL_SHARED-LLL_PRIVATE) > 255
538         xorl    %ecx, %ecx
539 #endif
540         cmpl    $-1, dep_mutex(%ebx)
541         setne   %cl
542         subl    $1, %ecx
543         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
544 #if LLL_PRIVATE != 0
545         addl    $LLL_PRIVATE, %ecx
546 #endif
547         call    __lll_lock_wait
549 1:      movl    broadcast_seq(%ebx), %eax
550         cmpl    20(%esp), %eax
551         jne     3f
553         /* We increment the wakeup_seq counter only if it is lower than
554            total_seq.  If this is not the case the thread was woken and
555            then canceled.  In this case we ignore the signal.  */
556         movl    total_seq(%ebx), %eax
557         movl    total_seq+4(%ebx), %edi
558         cmpl    wakeup_seq+4(%ebx), %edi
559         jb      6f
560         ja      7f
561         cmpl    wakeup_seq(%ebx), %eax
562         jbe     7f
564 6:      addl    $1, wakeup_seq(%ebx)
565         adcl    $0, wakeup_seq+4(%ebx)
566         addl    $1, cond_futex(%ebx)
568 7:      addl    $1, woken_seq(%ebx)
569         adcl    $0, woken_seq+4(%ebx)
571 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
573         /* Wake up a thread which wants to destroy the condvar object.  */
574         xorl    %edi, %edi
575         movl    total_seq(%ebx), %eax
576         andl    total_seq+4(%ebx), %eax
577         cmpl    $0xffffffff, %eax
578         jne     4f
579         movl    cond_nwaiters(%ebx), %eax
580         andl    $~((1 << nwaiters_shift) - 1), %eax
581         jne     4f
583         addl    $cond_nwaiters, %ebx
584         movl    $SYS_futex, %eax
585 #if FUTEX_PRIVATE_FLAG > 255
586         xorl    %ecx, %ecx
587 #endif
588         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
589         sete    %cl
590         subl    $1, %ecx
591 #ifdef __ASSUME_PRIVATE_FUTEX
592         andl    $FUTEX_PRIVATE_FLAG, %ecx
593 #else
594         andl    %gs:PRIVATE_FUTEX, %ecx
595 #endif
596         addl    $FUTEX_WAKE, %ecx
597         movl    $1, %edx
598         ENTER_KERNEL
599         subl    $cond_nwaiters, %ebx
600         movl    $1, %edi
602 4:      LOCK
603 #if cond_lock == 0
604         subl    $1, (%ebx)
605 #else
606         subl    $1, cond_lock(%ebx)
607 #endif
608         je      2f
610 #if cond_lock == 0
611         movl    %ebx, %eax
612 #else
613         leal    cond_lock(%ebx), %eax
614 #endif
615 #if (LLL_SHARED-LLL_PRIVATE) > 255
616         xorl    %ecx, %ecx
617 #endif
618         cmpl    $-1, dep_mutex(%ebx)
619         setne   %cl
620         subl    $1, %ecx
621         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
622 #if LLL_PRIVATE != 0
623         addl    $LLL_PRIVATE, %ecx
624 #endif
625         call    __lll_unlock_wake
627         /* Wake up all waiters to make sure no signal gets lost.  */
628 2:      testl   %edi, %edi
629         jnz     5f
630         addl    $cond_futex, %ebx
631 #if FUTEX_PRIVATE_FLAG > 255
632         xorl    %ecx, %ecx
633 #endif
634         cmpl    $-1, dep_mutex-cond_futex(%ebx)
635         sete    %cl
636         subl    $1, %ecx
637 #ifdef __ASSUME_PRIVATE_FUTEX
638         andl    $FUTEX_PRIVATE_FLAG, %ecx
639 #else
640         andl    %gs:PRIVATE_FUTEX, %ecx
641 #endif
642         addl    $FUTEX_WAKE, %ecx
643         movl    $SYS_futex, %eax
644         movl    $0x7fffffff, %edx
645         ENTER_KERNEL
647 5:      movl    24+FRAME_SIZE(%esp), %eax
648         call    __pthread_mutex_cond_lock
650         movl    %esi, (%esp)
651 .LcallUR:
652         call    _Unwind_Resume
653         hlt
654 .LENDCODE:
655         cfi_endproc
656         .size   __condvar_tw_cleanup, .-__condvar_tw_cleanup
659         .section .gcc_except_table,"a",@progbits
660 .LexceptSTART:
661         .byte   DW_EH_PE_omit                   # @LPStart format (omit)
662         .byte   DW_EH_PE_omit                   # @TType format (omit)
663         .byte   DW_EH_PE_sdata4                 # call-site format
664                                                 # DW_EH_PE_sdata4
665         .uleb128 .Lcstend-.Lcstbegin
666 .Lcstbegin:
667         .long   .LcleanupSTART-.LSTARTCODE
668         .long   .Ladd_cond_futex-.LcleanupSTART
669         .long   __condvar_tw_cleanup-.LSTARTCODE
670         .uleb128  0
671         .long   .Ladd_cond_futex-.LSTARTCODE
672         .long   .Lsub_cond_futex-.Ladd_cond_futex
673         .long   __condvar_tw_cleanup2-.LSTARTCODE
674         .uleb128  0
675         .long   .Lsub_cond_futex-.LSTARTCODE
676         .long   .LcleanupEND-.Lsub_cond_futex
677         .long   __condvar_tw_cleanup-.LSTARTCODE
678         .uleb128  0
679         .long   .LcallUR-.LSTARTCODE
680         .long   .LENDCODE-.LcallUR
681         .long   0
682         .uleb128  0
683 .Lcstend:
686 #ifdef SHARED
687         .hidden DW.ref.__gcc_personality_v0
688         .weak   DW.ref.__gcc_personality_v0
689         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
690         .align  4
691         .type   DW.ref.__gcc_personality_v0, @object
692         .size   DW.ref.__gcc_personality_v0, 4
693 DW.ref.__gcc_personality_v0:
694         .long   __gcc_personality_v0
695 #endif