Initial revision
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / pthread_once.S
blob747c8ec2d2264ab9c4299e8e1f26d69d920cfcbe
1 /* Copyright (C) 2002 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>
22 #ifndef UP
23 # define LOCK lock
24 #else
25 # define LOCK
26 #endif
28 #define SYS_futex       240
29 #define FUTEX_WAKE      1
31         .comm   __fork_generation, 4, 4
33         .text
36         .globl  __pthread_once
37         .type   __pthread_once,@function
38         .align  16
39 __pthread_once:
40         movl    4(%esp), %ecx
41         testl   $2, (%ecx)
42         jz      1f
43         xorl    %eax, %eax
44         ret
46 1:      pushl   %ebx
47         pushl   %esi
48         movl    %ecx, %ebx
49         xorl    %esi, %esi
51         /* Not yet initialized or initialization in progress.
52            Get the fork generation counter now.  */
53 6:      movl    (%ebx), %eax
54 #ifdef PIC
55         call    __i686.get_pc_thunk.cx
56         addl    $_GLOBAL_OFFSET_TABLE_, %ecx
57 #endif
59 5:      movl    %eax, %edx
61         testl   $2, %eax
62         jnz     4f
64         andl    $3, %edx
65 #ifdef PIC
66         orl     __fork_generation@GOTOFF(%ecx), %edx
67 #else
68         orl     __fork_generation, %edx
69 #endif
70         orl     $1, %edx
72         LOCK
73         cmpxchgl %edx, (%ebx)
74         jnz     5b
76         /* Check whether another thread already runs the initializer.  */
77         testl   $1, %eax
78         jz      3f      /* No -> do it.  */
80         /* Check whether the initializer execution was interrupted
81            by a fork.  */
82         xorl    %edx, %eax
83         testl   $0xfffffffc, %eax
84         jnz     3f      /* Different for generation -> run initializer.  */
86         /* Somebody else got here first.  Wait.  */
87         movl    %esi, %ecx              /* movl $FUTEX_WAIT, %ecx */
88         movl    $SYS_futex, %eax
89         int     $0x80
90         jmp     6b
92 3:      /* Call the initializer function after setting up the
93            cancellation handler.  */
94         subl    $16, %esp
96         /* Push the cleanup handler.  */
97 #ifdef PIC
98         leal    clear_once_control@GOTOFF(%ecx), %eax
99 #else
100         leal    clear_once_control, %eax
101 #endif
102         movl    %esp, %edx
103         pushl   %ebx
104         pushl   %eax
105         pushl   %edx
106         call    _GI_pthread_cleanup_push        /* Note: no @PLT.  */
108         movl    44(%esp), %eax
109         call    *%eax
111         /* Pop the cleanup handler.  This code depends on the once
112            handler and _pthread_cleanup_push not touch the content
113            of the stack.  Otherwise the first parameter would have
114            to be reloaded.  */
115         movl    $0, 4(%esp)
116         call    _GI_pthread_cleanup_pop /* Note: no @PLT.  */
118         addl    $28, %esp
120         /* Sucessful run of the initializer.  Signal that we are done.  */
121         LOCK
122         incl    (%ebx)
124         /* Wake up all other threads.  */
125         movl    $0x7fffffff, %edx
126         movl    $FUTEX_WAKE, %ecx
127         movl    $SYS_futex, %eax
128         int     $0x80
130 4:      popl    %esi
131         popl    %ebx
132         xorl    %eax, %eax
133         ret
135         .size   __pthread_once,.-__pthread_once
137         .globl  pthread_once
138 pthread_once = __pthread_once
141         .type   clear_once_control,@function
142         .align  16
143 clear_once_control:
144         pushl   %esi
145         pushl   %ebx
147         movl    4(%esp), %eax
148         movl    $0, (%eax)
150         xorl    %esi, %esi
151         movl    $0x7fffffff, %edx
152         movl    $FUTEX_WAKE, %ecx
153         movl    $SYS_futex, %eax
154         int     $0x80
156         popl    %ebx
157         popl    %esi
158         ret
159         .size   clear_once_control,.-clear_once_control
162 #ifdef PIC
163         .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
164         .globl  __i686.get_pc_thunk.cx
165         .hidden __i686.get_pc_thunk.cx
166         .type   __i686.get_pc_thunk.cx,@function
167 __i686.get_pc_thunk.cx:
168         movl (%esp), %ecx;
169         ret
170         .size   __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
171 #endif