]> git.ipfire.org Git - thirdparty/glibc.git/blob - nptl/sysdeps/pthread/createthread.c
[BZ #405]
[thirdparty/glibc.git] / nptl / sysdeps / pthread / createthread.c
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.
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 <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>
27
28 #include "kernel-features.h"
29
30
31 #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
32
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
38
39 #ifndef ARCH_CLONE
40 # define ARCH_CLONE __clone
41 #endif
42
43
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
50
51
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)
56 {
57 #ifdef PREPARE_CREATE
58 PREPARE_CREATE;
59 #endif
60
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);
66
67 if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
68 pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
69 {
70 /* Failed. If the thread is detached, remove the TCB here since
71 the caller cannot do this. The caller remembered the thread
72 as detached and cannot reverify that it is not since it must
73 not access the thread descriptor again. */
74 if (IS_DETACHED (pd))
75 __deallocate_stack (pd);
76
77 return errno;
78 }
79
80 /* Now we have the possibility to set scheduling parameters etc. */
81 if (__builtin_expect (stopped != 0, 0))
82 {
83 INTERNAL_SYSCALL_DECL (err);
84 int res = 0;
85
86 /* Set the affinity mask if necessary. */
87 if (attr->cpuset != NULL)
88 {
89 res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid,
90 sizeof (cpu_set_t), attr->cpuset);
91
92 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
93 {
94 /* The operation failed. We have to kill the thread. First
95 send it the cancellation signal. */
96 INTERNAL_SYSCALL_DECL (err2);
97 err_out:
98 #if __ASSUME_TGKILL
99 (void) INTERNAL_SYSCALL (tgkill, err2, 3,
100 THREAD_GETMEM (THREAD_SELF, pid),
101 pd->tid, SIGCANCEL);
102 #else
103 (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
104 #endif
105
106 return (INTERNAL_SYSCALL_ERROR_P (res, err)
107 ? INTERNAL_SYSCALL_ERRNO (res, err)
108 : 0);
109 }
110 }
111
112 /* Set the scheduling parameters. */
113 if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)
114 {
115 res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid,
116 pd->schedpolicy, &pd->schedparam);
117
118 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
119 goto err_out;
120 }
121 }
122
123 /* We now have for sure more than one thread. The main thread might
124 not yet have the flag set. No need to set the global variable
125 again if this is what we use. */
126 THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
127
128 return 0;
129 }
130
131
132 static int
133 create_thread (struct pthread *pd, const struct pthread_attr *attr,
134 STACK_VARIABLES_PARMS)
135 {
136 #ifdef TLS_TCB_AT_TP
137 assert (pd->header.tcb != NULL);
138 #endif
139
140 /* We rely heavily on various flags the CLONE function understands:
141
142 CLONE_VM, CLONE_FS, CLONE_FILES
143 These flags select semantics with shared address space and
144 file descriptors according to what POSIX requires.
145
146 CLONE_SIGNAL
147 This flag selects the POSIX signal semantics.
148
149 CLONE_SETTLS
150 The sixth parameter to CLONE determines the TLS area for the
151 new thread.
152
153 CLONE_PARENT_SETTID
154 The kernels writes the thread ID of the newly created thread
155 into the location pointed to by the fifth parameters to CLONE.
156
157 Note that it would be semantically equivalent to use
158 CLONE_CHILD_SETTID but it is be more expensive in the kernel.
159
160 CLONE_CHILD_CLEARTID
161 The kernels clears the thread ID of a thread that has called
162 sys_exit() in the location pointed to by the seventh parameter
163 to CLONE.
164
165 CLONE_DETACHED
166 No signal is generated if the thread exists and it is
167 automatically reaped.
168
169 The termination signal is chosen to be zero which means no signal
170 is sent. */
171 int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
172 | CLONE_SETTLS | CLONE_PARENT_SETTID
173 | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
174 #if __ASSUME_NO_CLONE_DETACHED == 0
175 | CLONE_DETACHED
176 #endif
177 | 0);
178
179 if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
180 {
181 /* The parent thread is supposed to report events. Check whether
182 the TD_CREATE event is needed, too. */
183 const int _idx = __td_eventword (TD_CREATE);
184 const uint32_t _mask = __td_eventmask (TD_CREATE);
185
186 if ((_mask & (__nptl_threads_events.event_bits[_idx]
187 | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
188 {
189 /* Create the thread. We always create the thread stopped
190 so that it does not get far before we tell the debugger. */
191 int res = do_clone (pd, attr, clone_flags, start_thread,
192 STACK_VARIABLES_ARGS, 1);
193 if (res == 0)
194 {
195 /* Now fill in the information about the new thread in
196 the newly created thread's data structure. We cannot let
197 the new thread do this since we don't know whether it was
198 already scheduled when we send the event. */
199 pd->eventbuf.eventnum = TD_CREATE;
200 pd->eventbuf.eventdata = pd;
201
202 /* Enqueue the descriptor. */
203 do
204 pd->nextevent = __nptl_last_event;
205 while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event,
206 pd, pd->nextevent)
207 != 0);
208
209 /* Now call the function which signals the event. */
210 __nptl_create_event ();
211
212 /* And finally restart the new thread. */
213 lll_unlock (pd->lock);
214 }
215
216 return res;
217 }
218 }
219
220 #ifdef NEED_DL_SYSINFO
221 assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd));
222 #endif
223
224 /* Determine whether the newly created threads has to be started
225 stopped since we have to set the scheduling parameters or set the
226 affinity. */
227 int stopped = 0;
228 if (attr != NULL && (attr->cpuset != NULL
229 || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0))
230 stopped = 1;
231
232 /* Actually create the thread. */
233 int res = do_clone (pd, attr, clone_flags, start_thread,
234 STACK_VARIABLES_ARGS, stopped);
235
236 if (res == 0 && stopped)
237 /* And finally restart the new thread. */
238 lll_unlock (pd->lock);
239
240 return res;
241 }