Updated to fedora-glibc-20041110T0839
[glibc.git] / nptl / sysdeps / pthread / createthread.c
blob25a2703ae139581bebbcd805bddc312ac27f3540
1 /* Copyright (C) 2002, 2003, 2004 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 <sched.h>
21 #include <setjmp.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <atomic.h>
25 #include <ldsodefs.h>
26 #include <tls.h>
28 #include "kernel-features.h"
31 #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
33 /* Unless otherwise specified, the thread "register" is going to be
34 initialized with a pointer to the TCB. */
35 #ifndef TLS_VALUE
36 # define TLS_VALUE pd
37 #endif
39 #ifndef ARCH_CLONE
40 # define ARCH_CLONE __clone
41 #endif
44 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
45 /* Variable set to a nonzero value if more than one thread runs or ran. */
46 int __pthread_multiple_threads attribute_hidden;
47 /* Pointer to the corresponding variable in libc. */
48 int *__libc_multiple_threads_ptr attribute_hidden;
49 #endif
52 static int
53 do_clone (struct pthread *pd, const struct pthread_attr *attr,
54 int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS,
55 int stopped)
57 #ifdef PREPARE_CREATE
58 PREPARE_CREATE;
59 #endif
61 if (stopped)
62 /* We Make sure the thread does not run far by forcing it to get a
63 lock. We lock it here too so that the new thread cannot continue
64 until we tell it to. */
65 lll_lock (pd->lock);
67 /* One more thread. We cannot have the thread do this itself, since it
68 might exist but not have been scheduled yet by the time we've returned
69 and need to check the value to behave correctly. We must do it before
70 creating the thread, in case it does get scheduled first and then
71 might mistakenly think it was the only thread. In the failure case,
72 we momentarily store a false value; this doesn't matter because there
73 is no kosher thing a signal handler interrupting us right here can do
74 that cares whether the thread count is correct. */
75 atomic_increment (&__nptl_nthreads);
77 if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
78 pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
80 atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */
82 /* Failed. If the thread is detached, remove the TCB here since
83 the caller cannot do this. The caller remembered the thread
84 as detached and cannot reverify that it is not since it must
85 not access the thread descriptor again. */
86 if (IS_DETACHED (pd))
87 __deallocate_stack (pd);
89 return errno;
92 /* Now we have the possibility to set scheduling parameters etc. */
93 if (__builtin_expect (stopped != 0, 0))
95 INTERNAL_SYSCALL_DECL (err);
96 int res = 0;
98 /* Set the affinity mask if necessary. */
99 if (attr->cpuset != NULL)
101 res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid,
102 sizeof (cpu_set_t), attr->cpuset);
104 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
106 /* The operation failed. We have to kill the thread. First
107 send it the cancellation signal. */
108 INTERNAL_SYSCALL_DECL (err2);
109 err_out:
110 #if __ASSUME_TGKILL
111 (void) INTERNAL_SYSCALL (tgkill, err2, 3,
112 THREAD_GETMEM (THREAD_SELF, pid),
113 pd->tid, SIGCANCEL);
114 #else
115 (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
116 #endif
118 return (INTERNAL_SYSCALL_ERROR_P (res, err)
119 ? INTERNAL_SYSCALL_ERRNO (res, err)
120 : 0);
124 /* Set the scheduling parameters. */
125 if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)
127 res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid,
128 pd->schedpolicy, &pd->schedparam);
130 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
131 goto err_out;
135 /* We now have for sure more than one thread. The main thread might
136 not yet have the flag set. No need to set the global variable
137 again if this is what we use. */
138 THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
140 return 0;
144 static int
145 create_thread (struct pthread *pd, const struct pthread_attr *attr,
146 STACK_VARIABLES_PARMS)
148 #ifdef TLS_TCB_AT_TP
149 assert (pd->header.tcb != NULL);
150 #endif
152 /* We rely heavily on various flags the CLONE function understands:
154 CLONE_VM, CLONE_FS, CLONE_FILES
155 These flags select semantics with shared address space and
156 file descriptors according to what POSIX requires.
158 CLONE_SIGNAL
159 This flag selects the POSIX signal semantics.
161 CLONE_SETTLS
162 The sixth parameter to CLONE determines the TLS area for the
163 new thread.
165 CLONE_PARENT_SETTID
166 The kernels writes the thread ID of the newly created thread
167 into the location pointed to by the fifth parameters to CLONE.
169 Note that it would be semantically equivalent to use
170 CLONE_CHILD_SETTID but it is be more expensive in the kernel.
172 CLONE_CHILD_CLEARTID
173 The kernels clears the thread ID of a thread that has called
174 sys_exit() in the location pointed to by the seventh parameter
175 to CLONE.
177 CLONE_DETACHED
178 No signal is generated if the thread exists and it is
179 automatically reaped.
181 The termination signal is chosen to be zero which means no signal
182 is sent. */
183 int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
184 | CLONE_SETTLS | CLONE_PARENT_SETTID
185 | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
186 #if __ASSUME_NO_CLONE_DETACHED == 0
187 | CLONE_DETACHED
188 #endif
189 | 0);
191 if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
193 /* The parent thread is supposed to report events. Check whether
194 the TD_CREATE event is needed, too. */
195 const int _idx = __td_eventword (TD_CREATE);
196 const uint32_t _mask = __td_eventmask (TD_CREATE);
198 if ((_mask & (__nptl_threads_events.event_bits[_idx]
199 | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
201 /* We always must have the thread start stopped. */
202 pd->stopped_start = true;
204 /* Create the thread. We always create the thread stopped
205 so that it does not get far before we tell the debugger. */
206 int res = do_clone (pd, attr, clone_flags, start_thread,
207 STACK_VARIABLES_ARGS, 1);
208 if (res == 0)
210 /* Now fill in the information about the new thread in
211 the newly created thread's data structure. We cannot let
212 the new thread do this since we don't know whether it was
213 already scheduled when we send the event. */
214 pd->eventbuf.eventnum = TD_CREATE;
215 pd->eventbuf.eventdata = pd;
217 /* Enqueue the descriptor. */
219 pd->nextevent = __nptl_last_event;
220 while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event,
221 pd, pd->nextevent)
222 != 0);
224 /* Now call the function which signals the event. */
225 __nptl_create_event ();
227 /* And finally restart the new thread. */
228 lll_unlock (pd->lock);
231 return res;
235 #ifdef NEED_DL_SYSINFO
236 assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd));
237 #endif
239 /* Determine whether the newly created threads has to be started
240 stopped since we have to set the scheduling parameters or set the
241 affinity. */
242 bool stopped = false;
243 if (attr != NULL && (attr->cpuset != NULL
244 || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0))
245 stopped = true;
246 pd->stopped_start = stopped;
248 /* Actually create the thread. */
249 int res = do_clone (pd, attr, clone_flags, start_thread,
250 STACK_VARIABLES_ARGS, stopped);
252 if (res == 0 && stopped)
253 /* And finally restart the new thread. */
254 lll_unlock (pd->lock);
256 return res;