1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003 Daniel M. Eischen <deischen@gdeb.com> 5 * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "namespace.h" 34 #include <sys/types.h> 35 #include <sys/rtprio.h> 36 #include <sys/signalvar.h> 37 #include <errno.h> 38 #include <link.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <stddef.h> 42 #include <pthread.h> 43 #include <pthread_np.h> 44 #include "un-namespace.h" 45 46 #include "libc_private.h" 47 #include "thr_private.h" 48 49 static int create_stack(struct pthread_attr *pattr); 50 static void thread_start(struct pthread *curthread); 51 52 __weak_reference(_pthread_create, pthread_create); 53 54 int 55 _pthread_create(pthread_t * __restrict thread, 56 const pthread_attr_t * __restrict attr, void *(*start_routine) (void *), 57 void * __restrict arg) 58 { 59 struct pthread *curthread, *new_thread; 60 struct thr_param param; 61 struct sched_param sched_param; 62 struct rtprio rtp; 63 sigset_t set, oset; 64 cpuset_t *cpusetp; 65 int i, cpusetsize, create_suspended, locked, old_stack_prot, ret; 66 67 cpusetp = NULL; 68 ret = cpusetsize = 0; 69 _thr_check_init(); 70 71 /* 72 * Tell libc and others now they need lock to protect their data. 73 */ 74 if (_thr_isthreaded() == 0) { 75 _malloc_first_thread(); 76 if (_thr_setthreaded(1)) 77 return (EAGAIN); 78 } 79 80 curthread = _get_curthread(); 81 if ((new_thread = _thr_alloc(curthread)) == NULL) 82 return (EAGAIN); 83 84 memset(¶m, 0, sizeof(param)); 85 86 if (attr == NULL || *attr == NULL) 87 /* Use the default thread attributes: */ 88 new_thread->attr = _pthread_attr_default; 89 else { 90 new_thread->attr = *(*attr); 91 cpusetp = new_thread->attr.cpuset; 92 cpusetsize = new_thread->attr.cpusetsize; 93 new_thread->attr.cpuset = NULL; 94 new_thread->attr.cpusetsize = 0; 95 } 96 if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) { 97 /* inherit scheduling contention scope */ 98 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) 99 new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; 100 else 101 new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM; 102 103 new_thread->attr.prio = curthread->attr.prio; 104 new_thread->attr.sched_policy = curthread->attr.sched_policy; 105 } 106 107 new_thread->tid = TID_TERMINATED; 108 109 old_stack_prot = _rtld_get_stack_prot(); 110 if (create_stack(&new_thread->attr) != 0) { 111 /* Insufficient memory to create a stack: */ 112 _thr_free(curthread, new_thread); 113 return (EAGAIN); 114 } 115 /* 116 * Write a magic value to the thread structure 117 * to help identify valid ones: 118 */ 119 new_thread->magic = THR_MAGIC; 120 new_thread->start_routine = start_routine; 121 new_thread->arg = arg; 122 new_thread->cancel_enable = 1; 123 new_thread->cancel_async = 0; 124 /* Initialize the mutex queue: */ 125 for (i = 0; i < TMQ_NITEMS; i++) 126 TAILQ_INIT(&new_thread->mq[i]); 127 128 /* Initialise hooks in the thread structure: */ 129 if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) { 130 new_thread->flags = THR_FLAGS_NEED_SUSPEND; 131 create_suspended = 1; 132 } else { 133 create_suspended = 0; 134 } 135 136 new_thread->state = PS_RUNNING; 137 138 if (new_thread->attr.flags & PTHREAD_CREATE_DETACHED) 139 new_thread->flags |= THR_FLAGS_DETACHED; 140 141 /* Add the new thread. */ 142 new_thread->refcount = 1; 143 _thr_link(curthread, new_thread); 144 145 /* 146 * Handle the race between __pthread_map_stacks_exec and 147 * thread linkage. 148 */ 149 if (old_stack_prot != _rtld_get_stack_prot()) 150 _thr_stack_fix_protection(new_thread); 151 152 /* Return thread pointer eariler so that new thread can use it. */ 153 (*thread) = new_thread; 154 if (SHOULD_REPORT_EVENT(curthread, TD_CREATE) || cpusetp != NULL) { 155 THR_THREAD_LOCK(curthread, new_thread); 156 locked = 1; 157 } else 158 locked = 0; 159 param.start_func = (void (*)(void *)) thread_start; 160 param.arg = new_thread; 161 param.stack_base = new_thread->attr.stackaddr_attr; 162 param.stack_size = new_thread->attr.stacksize_attr; 163 param.tls_base = (char *)new_thread->tcb; 164 param.tls_size = sizeof(struct tcb); 165 param.child_tid = &new_thread->tid; 166 param.parent_tid = &new_thread->tid; 167 param.flags = 0; 168 if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) 169 param.flags |= THR_SYSTEM_SCOPE; 170 if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) 171 param.rtp = NULL; 172 else { 173 sched_param.sched_priority = new_thread->attr.prio; 174 _schedparam_to_rtp(new_thread->attr.sched_policy, 175 &sched_param, &rtp); 176 param.rtp = &rtp; 177 } 178 179 /* Schedule the new thread. */ 180 if (create_suspended) { 181 SIGFILLSET(set); 182 SIGDELSET(set, SIGTRAP); 183 __sys_sigprocmask(SIG_SETMASK, &set, &oset); 184 new_thread->sigmask = oset; 185 SIGDELSET(new_thread->sigmask, SIGCANCEL); 186 } 187 188 ret = thr_new(¶m, sizeof(param)); 189 190 if (ret != 0) { 191 ret = errno; 192 /* 193 * Translate EPROCLIM into well-known POSIX code EAGAIN. 194 */ 195 if (ret == EPROCLIM) 196 ret = EAGAIN; 197 } 198 199 if (create_suspended) 200 __sys_sigprocmask(SIG_SETMASK, &oset, NULL); 201 202 if (ret != 0) { 203 if (!locked) 204 THR_THREAD_LOCK(curthread, new_thread); 205 new_thread->state = PS_DEAD; 206 new_thread->tid = TID_TERMINATED; 207 new_thread->flags |= THR_FLAGS_DETACHED; 208 new_thread->refcount--; 209 if (new_thread->flags & THR_FLAGS_NEED_SUSPEND) { 210 new_thread->cycle++; 211 _thr_umtx_wake(&new_thread->cycle, INT_MAX, 0); 212 } 213 _thr_try_gc(curthread, new_thread); /* thread lock released */ 214 atomic_add_int(&_thread_active_threads, -1); 215 } else if (locked) { 216 if (cpusetp != NULL) { 217 if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, 218 TID(new_thread), cpusetsize, cpusetp)) { 219 ret = errno; 220 /* kill the new thread */ 221 new_thread->force_exit = 1; 222 new_thread->flags |= THR_FLAGS_DETACHED; 223 _thr_try_gc(curthread, new_thread); 224 /* thread lock released */ 225 goto out; 226 } 227 } 228 229 _thr_report_creation(curthread, new_thread); 230 THR_THREAD_UNLOCK(curthread, new_thread); 231 } 232 out: 233 if (ret) 234 (*thread) = 0; 235 return (ret); 236 } 237 238 static int 239 create_stack(struct pthread_attr *pattr) 240 { 241 int ret; 242 243 /* Check if a stack was specified in the thread attributes: */ 244 if ((pattr->stackaddr_attr) != NULL) { 245 pattr->guardsize_attr = 0; 246 pattr->flags |= THR_STACK_USER; 247 ret = 0; 248 } 249 else 250 ret = _thr_stack_alloc(pattr); 251 return (ret); 252 } 253 254 static void 255 thread_start(struct pthread *curthread) 256 { 257 sigset_t set; 258 259 if (curthread->attr.suspend == THR_CREATE_SUSPENDED) 260 set = curthread->sigmask; 261 262 /* 263 * This is used as a serialization point to allow parent 264 * to report 'new thread' event to debugger or tweak new thread's 265 * attributes before the new thread does real-world work. 266 */ 267 THR_LOCK(curthread); 268 THR_UNLOCK(curthread); 269 270 if (curthread->force_exit) 271 _pthread_exit(PTHREAD_CANCELED); 272 273 if (curthread->attr.suspend == THR_CREATE_SUSPENDED) { 274 #if 0 275 /* Done in THR_UNLOCK() */ 276 _thr_ast(curthread); 277 #endif 278 279 /* 280 * Parent thread have stored signal mask for us, 281 * we should restore it now. 282 */ 283 __sys_sigprocmask(SIG_SETMASK, &set, NULL); 284 } 285 286 #ifdef _PTHREAD_FORCED_UNWIND 287 curthread->unwind_stackend = (char *)curthread->attr.stackaddr_attr + 288 curthread->attr.stacksize_attr; 289 #endif 290 291 /* Run the current thread's start routine with argument: */ 292 _pthread_exit(curthread->start_routine(curthread->arg)); 293 294 /* This point should never be reached. */ 295 PANIC("Thread has resumed after exit"); 296 } 297