if_vtnet - Default to link up, when VIRTIO_NET_F_STATUS is not negotiated.
[dragonfly.git] / lib / libc_r / uthread / uthread_create.c
blob26537604b11158ea6e5e9baac4380ced05b9eb83
1 /*
2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * $FreeBSD: src/lib/libc_r/uthread/uthread_create.c,v 1.24.2.6 2003/01/08 05:04:26 fjoe Exp $
33 * $DragonFly: src/lib/libc_r/uthread/uthread_create.c,v 1.6 2005/05/30 20:50:53 joerg Exp $
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <stddef.h>
41 #include <sys/time.h>
42 #include <sys/param.h>
43 #include <sys/mman.h>
44 #include <machine/reg.h>
45 #include <pthread.h>
46 #include "pthread_private.h"
47 #include "libc_private.h"
49 static u_int64_t next_uniqueid = 1;
51 #define OFF(f) offsetof(struct pthread, f)
52 int _thread_next_offset = OFF(tle.tqe_next);
53 int _thread_uniqueid_offset = OFF(uniqueid);
54 int _thread_state_offset = OFF(state);
55 int _thread_name_offset = OFF(name);
56 int _thread_ctx_offset = OFF(ctx);
57 #undef OFF
59 int _thread_PS_RUNNING_value = PS_RUNNING;
60 int _thread_PS_DEAD_value = PS_DEAD;
62 int
63 _pthread_create(pthread_t *thread, const pthread_attr_t *attr,
64 void *(*start_routine) (void *), void *arg)
66 struct pthread *curthread = _get_curthread();
67 struct itimerval itimer;
68 int f_gc = 0;
69 int ret = 0;
70 pthread_t gc_thread;
71 pthread_t new_thread;
72 pthread_attr_t pattr;
73 void *stack;
75 if (thread == NULL)
76 return (EINVAL);
79 * Locking functions in libc are required when there are
80 * threads other than the initial thread.
82 __isthreaded = 1;
84 /* Allocate memory for the thread structure: */
85 if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
86 /* Insufficient memory to create a thread: */
87 ret = EAGAIN;
88 } else {
89 /* Check if default thread attributes are required: */
90 if (attr == NULL || *attr == NULL) {
91 /* Use the default thread attributes: */
92 pattr = &pthread_attr_default;
93 } else {
94 pattr = *attr;
96 /* Check if a stack was specified in the thread attributes: */
97 if ((stack = pattr->stackaddr_attr) != NULL) {
99 /* Allocate memory for a default-size stack: */
100 else if (pattr->stacksize_attr == PTHREAD_STACK_DEFAULT) {
101 struct stack *spare_stack;
103 /* Allocate or re-use a default-size stack. */
106 * Use the garbage collector mutex for synchronization
107 * of the spare stack list.
109 if (pthread_mutex_lock(&_gc_mutex) != 0)
110 PANIC("Cannot lock gc mutex");
112 if ((spare_stack = SLIST_FIRST(&_stackq)) != NULL) {
113 /* Use the spare stack. */
114 SLIST_REMOVE_HEAD(&_stackq, qe);
116 /* Unlock the garbage collector mutex. */
117 if (pthread_mutex_unlock(&_gc_mutex) != 0)
118 PANIC("Cannot unlock gc mutex");
120 stack = sizeof(struct stack)
121 + (void *) spare_stack
122 - PTHREAD_STACK_DEFAULT;
123 } else {
124 /* Allocate a new stack. */
125 stack = _next_stack + PTHREAD_STACK_GUARD;
128 * Even if stack allocation fails, we don't want
129 * to try to use this location again, so
130 * unconditionally decrement _next_stack. Under
131 * normal operating conditions, the most likely
132 * reason for an mmap() error is a stack
133 * overflow of the adjacent thread stack.
135 _next_stack -= (PTHREAD_STACK_DEFAULT
136 + PTHREAD_STACK_GUARD);
138 /* Unlock the garbage collector mutex. */
139 if (pthread_mutex_unlock(&_gc_mutex) != 0)
140 PANIC("Cannot unlock gc mutex");
142 /* Stack: */
143 if (mmap(stack, PTHREAD_STACK_DEFAULT,
144 PROT_READ | PROT_WRITE, MAP_STACK,
145 -1, 0) == MAP_FAILED) {
146 ret = EAGAIN;
147 free(new_thread);
152 * The user wants a stack of a particular size. Lets hope they
153 * really know what they want, and simply malloc the stack.
155 else if ((stack = (void *) malloc(pattr->stacksize_attr))
156 == NULL) {
157 /* Insufficient memory to create a thread: */
158 ret = EAGAIN;
159 free(new_thread);
162 /* Check for errors: */
163 if (ret != 0) {
164 } else {
165 /* Initialise the thread structure: */
166 memset(new_thread, 0, sizeof(struct pthread));
167 new_thread->tcb = _libc_allocate_tls();
168 if (new_thread->tcb == NULL)
169 PANIC("Cannot allocate TLS and TCB");
170 new_thread->slice_usec = -1;
171 new_thread->stack = stack;
172 new_thread->start_routine = start_routine;
173 new_thread->arg = arg;
175 new_thread->cancelflags = PTHREAD_CANCEL_ENABLE |
176 PTHREAD_CANCEL_DEFERRED;
179 * Write a magic value to the thread structure
180 * to help identify valid ones:
182 new_thread->magic = PTHREAD_MAGIC;
184 /* Initialise the thread for signals: */
185 new_thread->sigmask = curthread->sigmask;
186 new_thread->sigmask_seqno = 0;
188 /* Initialize the signal frame: */
189 new_thread->curframe = NULL;
191 /* Initialise the jump buffer: */
192 _setjmp(new_thread->ctx.jb);
195 * Set up new stack frame so that it looks like it
196 * returned from a longjmp() to the beginning of
197 * _thread_start().
199 SET_RETURN_ADDR_JB(new_thread->ctx.jb, _thread_start);
201 /* The stack starts high and builds down: */
202 SET_STACK_JB(new_thread->ctx.jb,
203 (long)new_thread->stack + pattr->stacksize_attr
204 - sizeof(double));
206 /* Copy the thread attributes: */
207 memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
210 * Check if this thread is to inherit the scheduling
211 * attributes from its parent:
213 if (new_thread->attr.sched_inherit & PTHREAD_INHERIT_SCHED) {
214 /* Copy the scheduling attributes: */
215 new_thread->base_priority =
216 curthread->base_priority &
217 ~PTHREAD_SIGNAL_PRIORITY;
218 new_thread->attr.prio =
219 curthread->base_priority &
220 ~PTHREAD_SIGNAL_PRIORITY;
221 new_thread->attr.sched_policy =
222 curthread->attr.sched_policy;
223 } else {
225 * Use just the thread priority, leaving the
226 * other scheduling attributes as their
227 * default values:
229 new_thread->base_priority =
230 new_thread->attr.prio;
232 new_thread->active_priority = new_thread->base_priority;
233 new_thread->inherited_priority = 0;
235 /* Initialize joiner to NULL (no joiner): */
236 new_thread->joiner = NULL;
238 /* Initialize the mutex queue: */
239 TAILQ_INIT(&new_thread->mutexq);
241 /* Initialise hooks in the thread structure: */
242 new_thread->specific_data = NULL;
243 new_thread->cleanup = NULL;
244 new_thread->flags = 0;
245 new_thread->poll_data.nfds = 0;
246 new_thread->poll_data.fds = NULL;
247 new_thread->continuation = NULL;
250 * Defer signals to protect the scheduling queues
251 * from access by the signal handler:
253 _thread_kern_sig_defer();
256 * Initialise the unique id which GDB uses to
257 * track threads.
259 new_thread->uniqueid = next_uniqueid++;
262 * Check if the garbage collector thread
263 * needs to be started.
265 f_gc = (TAILQ_FIRST(&_thread_list) == _thread_initial);
267 /* Add the thread to the linked list of all threads: */
268 TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle);
270 if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
271 new_thread->flags |= PTHREAD_FLAGS_SUSPENDED;
272 new_thread->state = PS_SUSPENDED;
273 } else {
274 new_thread->state = PS_RUNNING;
275 PTHREAD_PRIOQ_INSERT_TAIL(new_thread);
279 * Undefer and handle pending signals, yielding
280 * if necessary.
282 _thread_kern_sig_undefer();
284 /* Return a pointer to the thread structure: */
285 (*thread) = new_thread;
287 if (f_gc != 0) {
288 /* Install the scheduling timer: */
289 itimer.it_interval.tv_sec = 0;
290 itimer.it_interval.tv_usec = _clock_res_usec;
291 itimer.it_value = itimer.it_interval;
292 if (setitimer(_ITIMER_SCHED_TIMER, &itimer,
293 NULL) != 0)
294 PANIC("Cannot set interval timer");
297 /* Schedule the new user thread: */
298 _thread_kern_sched(NULL);
301 * Start a garbage collector thread
302 * if necessary.
304 if (f_gc && pthread_create(&gc_thread,NULL,
305 _thread_gc,NULL) != 0)
306 PANIC("Can't create gc thread");
311 /* Return the status: */
312 return (ret);
315 void
316 _thread_start(void)
318 struct pthread *curthread = _get_curthread();
320 /* We just left the scheduler via longjmp: */
321 _thread_kern_in_sched = 0;
323 /* Run the current thread's start routine with argument: */
324 pthread_exit(curthread->start_routine(curthread->arg));
326 /* This point should never be reached. */
327 PANIC("Thread has resumed after exit");
330 __strong_reference(_pthread_create, pthread_create);