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