Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_once.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 #ifndef UP
21 # define LOCK lock
22 #else
23 # define LOCK
24 #endif
25
26 #define SYS_futex       202
27 #define FUTEX_WAKE      1
28
29         .comm   __fork_generation, 4, 4
30
31         .text
32
33
34         .globl  __pthread_once
35         .type   __pthread_once,@function
36         .align  16
37 __pthread_once:
38 .LSTARTCODE:
39         testl   $2, (%rdi)
40         jz      1f
41         xorl    %eax, %eax
42         retq
43
44         /* Preserve the function pointer.  */
45 1:      pushq   %rsi
46 .Lpush_rsi:
47         xorq    %r10, %r10
48
49         /* Not yet initialized or initialization in progress.
50            Get the fork generation counter now.  */
51 6:      movl    (%rdi), %eax
52
53 5:      movl    %eax, %edx
54
55         testl   $2, %eax
56         jnz     4f
57
58         andl    $3, %edx
59         orl     __fork_generation(%rip), %edx
60         orl     $1, %edx
61
62         LOCK
63         cmpxchgl %edx, (%rdi)
64         jnz     5b
65
66         /* Check whether another thread already runs the initializer.  */
67         testl   $1, %eax
68         jz      3f      /* No -> do it.  */
69
70         /* Check whether the initializer execution was interrupted
71            by a fork.  */
72         xorl    %edx, %eax
73         testl   $0xfffffffc, %eax
74         jnz     3f      /* Different for generation -> run initializer.  */
75
76         /* Somebody else got here first.  Wait.  */
77         movq    %r10, %rsi              /* movq $FUTEX_WAIT, %rsi */
78         movq    $SYS_futex, %rax
79         syscall
80         jmp     6b
81
82         /* Preserve the pointer to the control variable.  */
83 3:      pushq   %rdi
84 .Lpush_rdi:
85
86 .LcleanupSTART:
87         callq   *8(%rsp)
88 .LcleanupEND:
89
90         /* Get the control variable address back.  */
91         popq    %rdi
92 .Lpop_rdi:
93
94         /* Sucessful run of the initializer.  Signal that we are done.  */
95         LOCK
96         incl    (%rdi)
97
98         /* Wake up all other threads.  */
99         movl    $0x7fffffff, %edx
100         movl    $FUTEX_WAKE, %esi
101         movq    $SYS_futex, %rax
102         syscall
103
104 4:      addq    $8, %rsp
105 .Ladd:
106         xorq    %rax, %rax
107         retq
108
109         .size   __pthread_once,.-__pthread_once
110
111
112         .globl  __pthread_once_internal
113 __pthread_once_internal = __pthread_once
114
115         .globl  pthread_once
116 pthread_once = __pthread_once
117
118
119         .type   clear_once_control,@function
120         .align  16
121 clear_once_control:
122         movq    (%rsp), %rdi
123         movq    %rax, %r8
124         movl    $0, (%rdi)
125
126         movl    $0x7fffffff, %edx
127         movq    $FUTEX_WAKE, %rsi
128         movq    $SYS_futex, %rax
129         syscall
130
131         movq    %r8, %rdi
132 .LcallUR:
133         call    _Unwind_Resume@PLT
134         hlt
135 .LENDCODE:
136         .size   clear_once_control,.-clear_once_control
137
138
139         .section .gcc_except_table,"a",@progbits
140 .LexceptSTART:
141         .byte   0xff                            # @LPStart format (omit)
142         .byte   0xff                            # @TType format (omit)
143         .byte   0x01                            # call-site format
144                                                 # DW_EH_PE_uleb128
145         .uleb128 .Lcstend-.Lcstbegin
146 .Lcstbegin:
147         .uleb128 .LcleanupSTART-.LSTARTCODE
148         .uleb128 .LcleanupEND-.LcleanupSTART
149         .uleb128 clear_once_control-.LSTARTCODE
150         .uleb128  0
151         .uleb128 .LcallUR-.LSTARTCODE
152         .uleb128 .LENDCODE-.LcallUR
153         .uleb128 0
154         .uleb128  0
155 .Lcstend:
156
157
158         .section .eh_frame,"a",@progbits
159 .LSTARTFRAME:
160         .long   .LENDCIE-.LSTARTCIE             # Length of the CIE.
161 .LSTARTCIE:
162         .long   0                               # CIE ID.
163         .byte   1                               # Version number.
164 #ifdef SHARED
165         .string "zPLR"                          # NUL-terminated augmentation
166                                                 # string.
167 #else
168         .string "zPL"                           # NUL-terminated augmentation
169                                                 # string.
170 #endif
171         .uleb128 1                              # Code alignment factor.
172         .sleb128 -8                             # Data alignment factor.
173         .byte   16                              # Return address register
174                                                 # column.
175 #ifdef SHARED
176         .uleb128 7                              # Augmentation value length.
177         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
178                                                 # + DW_EH_PE_sdata4
179                                                 # + DW_EH_PE_indirect
180         .long   DW.ref.__gcc_personality_v0-.
181         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
182                                                 # + DW_EH_PE_sdata4.
183         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
184                                                 # + DW_EH_PE_sdata4.
185 #else
186         .uleb128 10                             # Augmentation value length.
187         .byte   0x0                             # Personality: absolute
188         .quad   __gcc_personality_v0
189         .byte   0x0                             # LSDA Encoding: absolute
190 #endif
191         .byte 0x0c                              # DW_CFA_def_cfa
192         .uleb128 7
193         .uleb128 8
194         .byte   0x90                            # DW_CFA_offset, column 0x10
195         .uleb128 1
196         .align 8
197 .LENDCIE:
198
199         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
200 .LSTARTFDE:
201         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
202 #ifdef SHARED
203         .long   .LSTARTCODE-.                   # PC-relative start address
204                                                 # of the code.
205         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
206         .uleb128 4                              # Augmentation size
207         .long   .LexceptSTART-.
208 #else
209         .quad   .LSTARTCODE                     # Start address of the code.
210         .quad   .LENDCODE-.LSTARTCODE           # Length of the code.
211         .uleb128 8                              # Augmentation size
212         .quad   .LexceptSTART
213 #endif
214         .byte   4                               # DW_CFA_advance_loc4
215         .long   .Lpush_rsi-.LSTARTCODE
216         .byte   14                              # DW_CFA_def_cfa_offset
217         .uleb128 16
218         .byte   4                               # DW_CFA_advance_loc4
219         .long   .Lpush_rdi-.Lpush_rsi
220         .byte   14                              # DW_CFA_def_cfa_offset
221         .uleb128 24
222         .byte   4                               # DW_CFA_advance_loc4
223         .long   .Lpop_rdi-.Lpush_rdi
224         .byte   14                              # DW_CFA_def_cfa_offset
225         .uleb128 16
226         .byte   4                               # DW_CFA_advance_loc4
227         .long   .Ladd-.Lpop_rdi
228         .byte   14                              # DW_CFA_def_cfa_offset
229         .uleb128 8
230         .byte   4                               # DW_CFA_advance_loc4
231         .long   clear_once_control-.Ladd
232         .byte   14                              # DW_CFA_def_cfa_offset
233         .uleb128 24
234 #if 0
235         .byte   4                               # DW_CFA_advance_loc4
236         .long   .Lpop_rdi2-clear_once_control
237         .byte   14                              # DW_CFA_def_cfa_offset
238         .uleb128 16
239 #endif
240         .align  8
241 .LENDFDE:
242
243
244 #ifdef SHARED
245         .hidden DW.ref.__gcc_personality_v0
246         .weak   DW.ref.__gcc_personality_v0
247         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
248         .align  8
249         .type   DW.ref.__gcc_personality_v0, @object
250         .size   DW.ref.__gcc_personality_v0, 8
251 DW.ref.__gcc_personality_v0:
252         .quad   __gcc_personality_v0
253 #endif