1 /* Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5 OpenSolaris bits contributed by David Bartley
6 <dtbartle@csclub.uwaterloo.ca>, 2008.
8 The GNU C Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 The GNU C Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the GNU C Library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 #include <sys/stack.h>
26 #include <sys/stack.h>
27 #include <sys/regset.h>
29 #include <inline-syscall.h>
31 #include <createthread_arch.c>
33 DECLARE_INLINE_SYSCALL (int, lwp_create, ucontext_t *ucp, int flags,
35 DECLARE_INLINE_SYSCALL (int, lwp_continue, pthread_t lwpid);
36 DECLARE_INLINE_SYSCALL (int, lwp_kill, pthread_t lwpid, int sig);
38 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
39 /* Pointer to the corresponding variable in libc. */
40 int *__libc_multiple_threads_ptr attribute_hidden;
44 create_thread (struct pthread *pd, const struct pthread_attr *attr,
45 STACK_VARIABLES_PARMS)
48 assert (pd->header.tcb != NULL);
51 /* Do arch-specific creation. */
53 int errval = create_thread_arch (&ctx, pd, attr, STACK_VARIABLES_ARGS);
57 /* Threads inherit the parent's sigmask. */
58 pthread_sigmask (SIG_SETMASK, NULL, &ctx.uc_sigmask);
60 /* One more thread. We cannot have the thread do this itself, since it
61 might exist but not have been scheduled yet by the time we've returned
62 and need to check the value to behave correctly. We must do it before
63 creating the thread, in case it does get scheduled first and then
64 might mistakenly think it was the only thread. In the failure case,
65 we momentarily store a false value; this doesn't matter because there
66 is no kosher thing a signal handler interrupting us right here can do
67 that cares whether the thread count is correct. */
68 atomic_increment (&__nptl_nthreads);
70 /* We set the thread to be initially suspended so that we can set
73 ((attr->flags & ATTR_FLAG_DAEMON) ? LWP_DAEMON : 0) |
74 ((attr->flags & ATTR_FLAG_DETACHSTATE) ? LWP_DETACHED : 0);
75 if ((attr->flags & ATTR_FLAG_THR_CREATE) == 0)
76 lwp_flags |= LWP_SUSPENDED;
77 errval = INLINE_SYSCALL (lwp_create, 3, &ctx, lwp_flags, &pd->tid);
78 if (errval == 0 && (attr->flags & ATTR_FLAG_THR_CREATE) == 0)
81 if (attr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
84 errval = __sched_getscheduler_id (P_LWPID, pd->tid,
88 if (attr->flags & ATTR_FLAG_SCHED_SET)
89 priority = attr->schedparam.__sched_priority;
90 if (attr->flags & ATTR_FLAG_POLICY_SET)
91 policy = attr->schedpolicy;
93 errval = __sched_setscheduler_id (P_LWPID, pd->tid,
101 /* Resume thread if requested. */
104 if (!(attr->flags & ATTR_FLAG_SUSPENDED))
105 errval = INLINE_SYSCALL (lwp_continue, 1, pd->tid);
108 /* Kill the thread if we didn't succeed above. */
110 INLINE_SYSCALL (lwp_kill, 2, pd->tid, SIGKILL);
115 /* We now have for sure more than one thread. The main thread might
116 not yet have the flag set. No need to set the global variable
117 again if this is what we use. */
118 THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
122 atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */
124 /* Failed. If the thread is detached, remove the TCB here since
125 the caller cannot do this. The caller remembered the thread
126 as detached and cannot reverify that it is not since it must
127 not access the thread descriptor again. */
128 if (IS_DETACHED (pd))
129 __deallocate_stack (pd);