]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libpthread / nptl / sysdeps / unix / sysv / linux / i386 / pthread_once.S
1 /* Copyright (C) 2002, 2003, 2007 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 <unwindbuf.h>
21 #include <sysdep.h>
22 #include <bits/kernel-features.h>
23 #include <lowlevellock.h>
24 #include <tls.h>
25
26
27         .comm   __fork_generation, 4, 4
28
29         .text
30
31
32         .globl  __pthread_once
33         .type   __pthread_once,@function
34         .protected      __pthread_once
35         .align  16
36         cfi_startproc
37 __pthread_once:
38         movl    4(%esp), %ecx
39         testl   $2, (%ecx)
40         jz      1f
41         xorl    %eax, %eax
42         ret
43
44 1:      pushl   %ebx
45         cfi_adjust_cfa_offset (4)
46         cfi_rel_offset (3, 0)
47         pushl   %esi
48         cfi_adjust_cfa_offset (4)
49         cfi_rel_offset (6, 0)
50         movl    %ecx, %ebx
51         xorl    %esi, %esi
52
53         /* Not yet initialized or initialization in progress.
54            Get the fork generation counter now.  */
55 6:      movl    (%ebx), %eax
56 #ifdef __PIC__
57         call    __x86.get_pc_thunk.cx
58         addl    $_GLOBAL_OFFSET_TABLE_, %ecx
59 #endif
60
61 5:      movl    %eax, %edx
62
63         testl   $2, %eax
64         jnz     4f
65
66         andl    $3, %edx
67 #ifdef __PIC__
68         orl     __fork_generation@GOTOFF(%ecx), %edx
69 #else
70         orl     __fork_generation, %edx
71 #endif
72         orl     $1, %edx
73
74         LOCK
75         cmpxchgl %edx, (%ebx)
76         jnz     5b
77
78         /* Check whether another thread already runs the initializer.  */
79         testl   $1, %eax
80         jz      3f      /* No -> do it.  */
81
82         /* Check whether the initializer execution was interrupted
83            by a fork.  */
84         xorl    %edx, %eax
85         testl   $0xfffffffc, %eax
86         jnz     3f      /* Different for generation -> run initializer.  */
87
88         /* Somebody else got here first.  Wait.  */
89 #ifdef __ASSUME_PRIVATE_FUTEX
90         movl    $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %ecx
91 #else
92 # if FUTEX_WAIT == 0
93         movl    %gs:PRIVATE_FUTEX, %ecx
94 # else
95         movl    $FUTEX_WAIT, %ecx
96         orl     %gs:PRIVATE_FUTEX, %ecx
97 # endif
98 #endif
99         movl    $SYS_futex, %eax
100         ENTER_KERNEL
101         jmp     6b
102
103 3:      /* Call the initializer function after setting up the
104            cancellation handler.  Note that it is not possible here
105            to use the unwind-based cleanup handling.  This would require
106            that the user-provided function and all the code it calls
107            is compiled with exceptions.  Unfortunately this cannot be
108            guaranteed.  */
109         subl    $UNWINDBUFSIZE+8, %esp
110         cfi_adjust_cfa_offset (UNWINDBUFSIZE+8)
111         movl    %ecx, %ebx              /* PIC register value.  */
112
113         leal    8+UWJMPBUF(%esp), %eax
114         movl    $0, 4(%esp)
115         movl    %eax, (%esp)
116         call    __sigsetjmp@PLT
117         testl   %eax, %eax
118         jne     7f
119
120         leal    8(%esp), %eax
121         call    HIDDEN_JUMPTARGET(__pthread_register_cancel)
122
123         /* Call the user-provided initialization function.  */
124         call    *24+UNWINDBUFSIZE(%esp)
125
126         /* Pop the cleanup handler.  */
127         leal    8(%esp), %eax
128         call    HIDDEN_JUMPTARGET(__pthread_unregister_cancel)
129         addl    $UNWINDBUFSIZE+8, %esp
130         cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8)
131
132         /* Sucessful run of the initializer.  Signal that we are done.  */
133         movl    12(%esp), %ebx
134         LOCK
135         addl    $1, (%ebx)
136
137         /* Wake up all other threads.  */
138         movl    $0x7fffffff, %edx
139 #ifdef __ASSUME_PRIVATE_FUTEX
140         movl    $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx
141 #else
142         movl    $FUTEX_WAKE, %ecx
143         orl     %gs:PRIVATE_FUTEX, %ecx
144 #endif
145         movl    $SYS_futex, %eax
146         ENTER_KERNEL
147
148 4:      popl    %esi
149         cfi_adjust_cfa_offset (-4)
150         cfi_restore (6)
151         popl    %ebx
152         cfi_adjust_cfa_offset (-4)
153         cfi_restore (3)
154         xorl    %eax, %eax
155         ret
156
157 7:      /* __sigsetjmp returned for the second time.  */
158         movl    20+UNWINDBUFSIZE(%esp), %ebx
159         cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
160         cfi_offset (3, -8)
161         cfi_offset (6, -12)
162         movl    $0, (%ebx)
163
164         movl    $0x7fffffff, %edx
165 #ifdef __ASSUME_PRIVATE_FUTEX
166         movl    $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx
167 #else
168         movl    $FUTEX_WAKE, %ecx
169         orl     %gs:PRIVATE_FUTEX, %ecx
170 #endif
171         movl    $SYS_futex, %eax
172         ENTER_KERNEL
173
174         leal    8(%esp), %eax
175         call    HIDDEN_JUMPTARGET (__pthread_unwind_next)
176         /* NOTREACHED */
177         hlt
178         cfi_endproc
179         .size   __pthread_once,.-__pthread_once
180
181         .globl  __pthread_once_internal
182 __pthread_once_internal = __pthread_once
183
184         .globl  pthread_once
185 pthread_once = __pthread_once
186
187
188 #ifdef __PIC__
189         .section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits
190         .globl  __x86.get_pc_thunk.cx
191         .hidden __x86.get_pc_thunk.cx
192         .type   __x86.get_pc_thunk.cx,@function
193 __x86.get_pc_thunk.cx:
194         movl (%esp), %ecx;
195         ret
196         .size   __x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx
197 #endif