]>
Commit | Line | Data |
---|---|---|
0ecb606c | 1 | /* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. |
76a50749 UD |
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 | ||
88ff4759 | 20 | #include <assert.h> |
76a50749 UD |
21 | #include <stdlib.h> |
22 | #include <unistd.h> | |
23 | #include <sys/types.h> | |
24 | #include <sysdep.h> | |
25 | #include <libio/libioP.h> | |
26 | #include <tls.h> | |
27 | #include "fork.h" | |
88ff4759 UD |
28 | #include <hp-timing.h> |
29 | #include <ldsodefs.h> | |
d3c9f895 | 30 | #include <bits/stdio-lock.h> |
92d83c72 | 31 | #include <atomic.h> |
76a50749 UD |
32 | |
33 | ||
34 | unsigned long int *__fork_generation_pointer; | |
35 | ||
36 | ||
92d83c72 UD |
37 | |
38 | /* The single linked list of all currently registered for handlers. */ | |
39 | struct fork_handler *__fork_handlers; | |
76a50749 UD |
40 | |
41 | ||
42 | static void | |
43 | fresetlockfiles (void) | |
44 | { | |
45 | _IO_ITER i; | |
46 | ||
47 | for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i)) | |
d3c9f895 | 48 | _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock)); |
76a50749 UD |
49 | } |
50 | ||
51 | ||
52 | pid_t | |
53 | __libc_fork (void) | |
54 | { | |
55 | pid_t pid; | |
92d83c72 UD |
56 | struct used_handler |
57 | { | |
58 | struct fork_handler *handler; | |
59 | struct used_handler *next; | |
60 | } *allp = NULL; | |
61 | ||
62 | /* Run all the registered preparation handlers. In reverse order. | |
63 | While doing this we build up a list of all the entries. */ | |
64 | struct fork_handler *runp; | |
65 | while ((runp = __fork_handlers) != NULL) | |
76a50749 | 66 | { |
92d83c72 UD |
67 | unsigned int oldval = runp->refcntr; |
68 | ||
69 | if (oldval == 0) | |
70 | /* This means some other thread removed the list just after | |
71 | the pointer has been loaded. Try again. Either the list | |
72 | is empty or we can retry it. */ | |
73 | continue; | |
74 | ||
75 | /* Bump the reference counter. */ | |
76 | if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, | |
77 | oldval + 1, oldval)) | |
78 | /* The value changed, try again. */ | |
79 | continue; | |
80 | ||
81 | /* We bumped the reference counter for the first entry in the | |
82 | list. That means that none of the following entries will | |
83 | just go away. The unloading code works in the order of the | |
84 | list. | |
85 | ||
86 | While executing the registered handlers we are building a | |
87 | list of all the entries so that we can go backward later on. */ | |
88 | while (1) | |
89 | { | |
90 | /* Execute the handler if there is one. */ | |
91 | if (runp->prepare_handler != NULL) | |
92 | runp->prepare_handler (); | |
93 | ||
94 | /* Create a new element for the list. */ | |
95 | struct used_handler *newp | |
96 | = (struct used_handler *) alloca (sizeof (*newp)); | |
97 | newp->handler = runp; | |
98 | newp->next = allp; | |
99 | allp = newp; | |
100 | ||
101 | /* Advance to the next handler. */ | |
102 | runp = runp->next; | |
103 | if (runp == NULL) | |
104 | break; | |
105 | ||
106 | /* Bump the reference counter for the next entry. */ | |
107 | atomic_increment (&runp->refcntr); | |
108 | } | |
76a50749 | 109 | |
92d83c72 UD |
110 | /* We are done. */ |
111 | break; | |
76a50749 UD |
112 | } |
113 | ||
114 | _IO_list_lock (); | |
115 | ||
0579fabb | 116 | #ifndef NDEBUG |
0bb2ac85 | 117 | pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); |
0579fabb | 118 | #endif |
0bb2ac85 | 119 | |
c0ecb80a UD |
120 | /* We need to prevent the getpid() code to update the PID field so |
121 | that, if a signal arrives in the child very early and the signal | |
122 | handler uses getpid(), the value returned is correct. */ | |
123 | pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); | |
124 | THREAD_SETMEM (THREAD_SELF, pid, -parentpid); | |
125 | ||
76a50749 UD |
126 | #ifdef ARCH_FORK |
127 | pid = ARCH_FORK (); | |
128 | #else | |
129 | # error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" | |
130 | pid = INLINE_SYSCALL (fork, 0); | |
131 | #endif | |
132 | ||
0bb2ac85 | 133 | |
76a50749 UD |
134 | if (pid == 0) |
135 | { | |
88ff4759 UD |
136 | struct pthread *self = THREAD_SELF; |
137 | ||
138 | assert (THREAD_GETMEM (self, tid) != ppid); | |
0bb2ac85 | 139 | |
76a50749 UD |
140 | if (__fork_generation_pointer != NULL) |
141 | *__fork_generation_pointer += 4; | |
142 | ||
db54f488 | 143 | /* Adjust the PID field for the new process. */ |
c0ecb80a | 144 | THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); |
db54f488 | 145 | |
88ff4759 UD |
146 | #if HP_TIMING_AVAIL |
147 | /* The CPU clock of the thread and process have to be set to zero. */ | |
148 | hp_timing_t now; | |
149 | HP_TIMING_NOW (now); | |
150 | THREAD_SETMEM (self, cpuclock_offset, now); | |
151 | GL(dl_cpuclock_offset) = now; | |
152 | #endif | |
153 | ||
76a50749 UD |
154 | /* Reset the file list. These are recursive mutexes. */ |
155 | fresetlockfiles (); | |
156 | ||
dfdd294a | 157 | /* Reset locks in the I/O code. */ |
76a50749 UD |
158 | _IO_list_resetlock (); |
159 | ||
1d9d0b80 UD |
160 | /* Reset the lock the dynamic loader uses to protect its data. */ |
161 | __rtld_lock_initialize (GL(dl_load_lock)); | |
162 | ||
76a50749 | 163 | /* Run the handlers registered for the child. */ |
92d83c72 | 164 | while (allp != NULL) |
76a50749 | 165 | { |
92d83c72 UD |
166 | if (allp->handler->child_handler != NULL) |
167 | allp->handler->child_handler (); | |
76a50749 | 168 | |
92d83c72 | 169 | /* Note that we do not have to wake any possible waiter. |
0ecb606c JJ |
170 | This is the only thread in the new process. The count |
171 | may have been bumped up by other threads doing a fork. | |
172 | We reset it to 1, to avoid waiting for non-existing | |
173 | thread(s) to release the count. */ | |
174 | allp->handler->refcntr = 1; | |
76a50749 | 175 | |
92d83c72 UD |
176 | /* XXX We could at this point look through the object pool |
177 | and mark all objects not on the __fork_handlers list as | |
178 | unused. This is necessary in case the fork() happened | |
179 | while another thread called dlclose() and that call had | |
180 | to create a new list. */ | |
181 | ||
182 | allp = allp->next; | |
76a50749 UD |
183 | } |
184 | ||
185 | /* Initialize the fork lock. */ | |
186 | __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER; | |
187 | } | |
188 | else | |
189 | { | |
0bb2ac85 RM |
190 | assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); |
191 | ||
c0ecb80a UD |
192 | /* Restore the PID value. */ |
193 | THREAD_SETMEM (THREAD_SELF, pid, parentpid); | |
194 | ||
76a50749 UD |
195 | /* We execute this even if the 'fork' call failed. */ |
196 | _IO_list_unlock (); | |
197 | ||
198 | /* Run the handlers registered for the parent. */ | |
92d83c72 | 199 | while (allp != NULL) |
76a50749 | 200 | { |
92d83c72 UD |
201 | if (allp->handler->parent_handler != NULL) |
202 | allp->handler->parent_handler (); | |
76a50749 | 203 | |
92d83c72 UD |
204 | if (atomic_decrement_and_test (&allp->handler->refcntr) |
205 | && allp->handler->need_signal) | |
206 | lll_futex_wake (allp->handler->refcntr, 1); | |
76a50749 | 207 | |
92d83c72 | 208 | allp = allp->next; |
76a50749 | 209 | } |
76a50749 UD |
210 | } |
211 | ||
212 | return pid; | |
213 | } | |
214 | weak_alias (__libc_fork, __fork) | |
4baa087a | 215 | libc_hidden_def (__fork) |
76a50749 | 216 | weak_alias (__libc_fork, fork) |