(pthread_barrier_wait): Don't save, load, and restore %esi for last thread.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / fork.c
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 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sysdep.h>
24 #include <libio/libioP.h>
25 #include <tls.h>
26 #include "fork.h"
27 #include <bits/stdio-lock.h>
28
29
30 unsigned long int *__fork_generation_pointer;
31
32
33 lll_lock_t __fork_lock = LLL_LOCK_INITIALIZER;
34 LIST_HEAD (__fork_prepare_list);
35 LIST_HEAD (__fork_parent_list);
36 LIST_HEAD (__fork_child_list);
37
38
39 static void
40 fresetlockfiles (void)
41 {
42   _IO_ITER i;
43
44   for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
45     _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
46 }
47
48
49 pid_t
50 __libc_fork (void)
51 {
52   pid_t pid;
53   list_t *runp;
54
55   /* Get the lock so that the set of registered handlers is not
56      inconsistent or changes beneath us.  */
57   lll_lock (__fork_lock);
58
59   /* Run all the registered preparation handlers.  In reverse order.  */
60   list_for_each_prev (runp, &__fork_prepare_list)
61     {
62       struct fork_handler *curp;
63
64       curp = list_entry (runp, struct fork_handler, list);
65
66       curp->handler ();
67     }
68
69   _IO_list_lock ();
70
71 #ifdef ARCH_FORK
72   pid = ARCH_FORK ();
73 #else
74 # error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used"
75   pid = INLINE_SYSCALL (fork, 0);
76 #endif
77
78   if (pid == 0)
79     {
80       if (__fork_generation_pointer != NULL)
81         *__fork_generation_pointer += 4;
82
83       /* Reset the file list.  These are recursive mutexes.  */
84       fresetlockfiles ();
85
86       /* Reset locks in the I/O code.  */
87       _IO_list_resetlock ();
88
89       /* Run the handlers registered for the child.  */
90       list_for_each (runp, &__fork_child_list)
91         {
92           struct fork_handler *curp;
93
94           curp = list_entry (runp, struct fork_handler, list);
95
96           curp->handler ();
97         }
98
99       /* Initialize the fork lock.  */
100       __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER;
101     }
102   else
103     {
104       /* We execute this even if the 'fork' call failed.  */
105       _IO_list_unlock ();
106
107       /* Run the handlers registered for the parent.  */
108       list_for_each (runp, &__fork_parent_list)
109         {
110           struct fork_handler *curp;
111
112           curp = list_entry (runp, struct fork_handler, list);
113
114           curp->handler ();
115         }
116
117       /* Release the for lock.  */
118       lll_unlock (__fork_lock);
119     }
120
121   return pid;
122 }
123 weak_alias (__libc_fork, __fork)
124 weak_alias (__libc_fork, fork)