2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * Copyright (c) 2003 Daniel M. Eischen <deischen@gdeb.com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/lib/libpthread/thread/thr_create.c,v 1.58 2004/10/23 23:28:36 davidxu Exp $
29 #include "namespace.h"
37 #include <machine/reg.h>
38 #include <machine/tls.h>
40 #include <sys/signalvar.h>
42 #include "un-namespace.h"
44 #include "libc_private.h"
45 #include "thr_private.h"
47 static int create_stack(struct pthread_attr
*pattr
);
48 static void thread_start(void *);
51 _pthread_create(pthread_t
* thread
, const pthread_attr_t
* attr
,
52 void *(*start_routine
) (void *), void *arg
)
54 struct lwp_params create_params
;
56 sigset_t sigmask
, oldsigmask
;
57 struct pthread
*curthread
, *new_thread
;
58 const cpu_set_t
*cpumask
= NULL
;
64 * Tell libc and others now they need lock to protect their data.
66 if (_thr_isthreaded() == 0 && _thr_setthreaded(1))
69 curthread
= tls_get_curthread();
70 if ((new_thread
= _thr_alloc(curthread
)) == NULL
)
73 if (attr
== NULL
|| *attr
== NULL
) {
74 /* Use the default thread attributes: */
75 new_thread
->attr
= _pthread_attr_default
;
77 new_thread
->attr
= *(*attr
);
79 if (new_thread
->attr
.sched_inherit
== PTHREAD_INHERIT_SCHED
) {
80 /* inherit scheduling contention scope */
81 if (curthread
->attr
.flags
& PTHREAD_SCOPE_SYSTEM
)
82 new_thread
->attr
.flags
|= PTHREAD_SCOPE_SYSTEM
;
84 new_thread
->attr
.flags
&= ~PTHREAD_SCOPE_SYSTEM
;
86 * scheduling policy and scheduling parameters will be
87 * inherited in following code.
90 if (new_thread
->attr
.flags
& THR_CPUMASK
)
91 cpumask
= &new_thread
->attr
.cpumask
;
93 if (create_stack(&new_thread
->attr
) != 0) {
94 /* Insufficient memory to create a stack: */
95 new_thread
->terminated
= 1;
96 _thr_free(curthread
, new_thread
);
100 * Write a magic value to the thread structure
101 * to help identify valid ones:
103 new_thread
->magic
= THR_MAGIC
;
104 new_thread
->start_routine
= start_routine
;
105 new_thread
->arg
= arg
;
106 new_thread
->cancelflags
= PTHREAD_CANCEL_ENABLE
|
107 PTHREAD_CANCEL_DEFERRED
;
109 * Check if this thread is to inherit the scheduling
110 * attributes from its parent:
112 if (new_thread
->attr
.sched_inherit
== PTHREAD_INHERIT_SCHED
) {
114 * Copy the scheduling attributes. Lock the scheduling
115 * lock to get consistent scheduling parameters.
118 new_thread
->base_priority
= curthread
->base_priority
;
119 new_thread
->attr
.prio
= curthread
->attr
.prio
;
120 new_thread
->attr
.sched_policy
= curthread
->attr
.sched_policy
;
121 THR_UNLOCK(curthread
);
124 * Use just the thread priority, leaving the
125 * other scheduling attributes as their
128 new_thread
->base_priority
= new_thread
->attr
.prio
;
130 new_thread
->active_priority
= new_thread
->base_priority
;
132 /* Initialize the mutex queue: */
133 TAILQ_INIT(&new_thread
->mutexq
);
135 /* Initialise hooks in the thread structure: */
136 if (new_thread
->attr
.suspend
== THR_CREATE_SUSPENDED
)
137 new_thread
->flags
= THR_FLAGS_NEED_SUSPEND
;
139 new_thread
->state
= PS_RUNNING
;
141 if (new_thread
->attr
.flags
& PTHREAD_CREATE_DETACHED
)
142 new_thread
->tlflags
|= TLFLAGS_DETACHED
;
144 /* Add the new thread. */
145 new_thread
->refcount
= 1;
146 _thr_link(curthread
, new_thread
);
147 /* Return thread pointer eariler so that new thread can use it. */
148 (*thread
) = new_thread
;
149 if (SHOULD_REPORT_EVENT(curthread
, TD_CREATE
)) {
150 THR_THREAD_LOCK(curthread
, new_thread
);
154 /* Schedule the new thread. */
155 stack
= (char *)new_thread
->attr
.stackaddr_attr
+
156 new_thread
->attr
.stacksize_attr
;
157 bzero(&create_params
, sizeof(create_params
));
158 create_params
.lwp_func
= thread_start
;
159 create_params
.lwp_arg
= new_thread
;
160 create_params
.lwp_stack
= stack
;
161 create_params
.lwp_tid1
= &new_thread
->tid
;
163 * Thread created by thr_create() inherits currrent thread
164 * sigmask, however, before new thread setup itself correctly,
165 * it can not handle signal, so we should mask all signals here.
166 * We do this at the very last moment, so that we don't run
167 * into problems while we have all signals disabled.
170 __sys_sigprocmask(SIG_SETMASK
, &sigmask
, &oldsigmask
);
171 new_thread
->sigmask
= oldsigmask
;
172 ret
= lwp_create2(&create_params
, cpumask
);
173 __sys_sigprocmask(SIG_SETMASK
, &oldsigmask
, NULL
);
176 THR_THREAD_LOCK(curthread
, new_thread
);
177 new_thread
->state
= PS_DEAD
;
178 new_thread
->terminated
= 1;
179 if (new_thread
->flags
& THR_FLAGS_NEED_SUSPEND
) {
181 _thr_umtx_wake(&new_thread
->cycle
, INT_MAX
);
183 THR_THREAD_UNLOCK(curthread
, new_thread
);
184 THREAD_LIST_LOCK(curthread
);
185 _thread_active_threads
--;
186 new_thread
->tlflags
|= TLFLAGS_DETACHED
;
187 _thr_ref_delete_unlocked(curthread
, new_thread
);
188 THREAD_LIST_UNLOCK(curthread
);
192 _thr_report_creation(curthread
, new_thread
);
193 THR_THREAD_UNLOCK(curthread
, new_thread
);
199 create_stack(struct pthread_attr
*pattr
)
203 /* Check if a stack was specified in the thread attributes: */
204 if ((pattr
->stackaddr_attr
) != NULL
) {
205 pattr
->guardsize_attr
= 0;
206 pattr
->flags
|= THR_STACK_USER
;
210 ret
= _thr_stack_alloc(pattr
);
215 thread_start(void *arg
)
217 struct pthread
*curthread
= (struct pthread
*)arg
;
219 tls_set_tcb(curthread
->tcb
);
221 /* Thread was created with all signals blocked, unblock them. */
222 __sys_sigprocmask(SIG_SETMASK
, &curthread
->sigmask
, NULL
);
225 THR_UNLOCK(curthread
);
227 if (curthread
->flags
& THR_FLAGS_NEED_SUSPEND
)
228 _thr_suspend_check(curthread
);
231 /* Run the current thread's start routine with argument: */
232 _pthread_exit(curthread
->start_routine(curthread
->arg
));
234 /* This point should never be reached. */
235 PANIC("Thread has resumed after exit");
238 __strong_reference(_pthread_create
, pthread_create
);