1 /* 2 * create.c 3 * 4 * Description: 5 * This translation unit implements routines associated with spawning a new 6 * thread. 7 * 8 * -------------------------------------------------------------------------- 9 * 10 * Pthreads-win32 - POSIX Threads Library for Win32 11 * Copyright(C) 1998 John E. Bossom 12 * Copyright(C) 1999,2005 Pthreads-win32 contributors 13 * 14 * Contact Email: rpj (at) callisto.canberra.edu.au 15 * 16 * The current list of contributors is contained 17 * in the file CONTRIBUTORS included with the source 18 * code distribution. The list can also be seen at the 19 * following World Wide Web location: 20 * http://sources.redhat.com/pthreads-win32/contributors.html 21 * 22 * This library is free software; you can redistribute it and/or 23 * modify it under the terms of the GNU Lesser General Public 24 * License as published by the Free Software Foundation; either 25 * version 2 of the License, or (at your option) any later version. 26 * 27 * This library is distributed in the hope that it will be useful, 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 * Lesser General Public License for more details. 31 * 32 * You should have received a copy of the GNU Lesser General Public 33 * License along with this library in the file COPYING.LIB; 34 * if not, write to the Free Software Foundation, Inc., 35 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 36 */ 37 38 #include "pthread.h" 39 #include "implement.h" 40 #if ! defined(_UWIN) && ! defined(WINCE) 41 #include <process.h> 42 #endif 43 44 int 45 pthread_create (pthread_t * tid, 46 const pthread_attr_t * attr, 47 void *(PTW32_CDECL *start) (void *), void *arg) 48 /* 49 * ------------------------------------------------------ 50 * DOCPUBLIC 51 * This function creates a thread running the start function, 52 * passing it the parameter value, 'arg'. The 'attr' 53 * argument specifies optional creation attributes. 54 * The identity of the new thread is returned 55 * via 'tid', which should not be NULL. 56 * 57 * PARAMETERS 58 * tid 59 * pointer to an instance of pthread_t 60 * 61 * attr 62 * optional pointer to an instance of pthread_attr_t 63 * 64 * start 65 * pointer to the starting routine for the new thread 66 * 67 * arg 68 * optional parameter passed to 'start' 69 * 70 * 71 * DESCRIPTION 72 * This function creates a thread running the start function, 73 * passing it the parameter value, 'arg'. The 'attr' 74 * argument specifies optional creation attributes. 75 * The identity of the new thread is returned 76 * via 'tid', which should not be the NULL pointer. 77 * 78 * RESULTS 79 * 0 successfully created thread, 80 * EINVAL attr invalid, 81 * EAGAIN insufficient resources. 82 * 83 * ------------------------------------------------------ 84 */ 85 { 86 pthread_t thread; 87 ptw32_thread_t * tp; 88 register pthread_attr_t a; 89 HANDLE threadH = 0; 90 int result = EAGAIN; 91 int run = PTW32_TRUE; 92 ThreadParms *parms = NULL; 93 unsigned int stackSize; 94 int priority; 95 pthread_t self; 96 97 /* 98 * Before doing anything, check that tid can be stored through 99 * without invoking a memory protection error (segfault). 100 * Make sure that the assignment below can't be optimised out by the compiler. 101 * This is assured by conditionally assigning *tid again at the end. 102 */ 103 tid->x = 0; 104 105 if (attr != NULL) 106 { 107 a = *attr; 108 } 109 else 110 { 111 a = NULL; 112 } 113 114 if ((thread = ptw32_new ()).p == NULL) 115 { 116 goto FAIL0; 117 } 118 119 tp = (ptw32_thread_t *) thread.p; 120 121 priority = tp->sched_priority; 122 123 if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL) 124 { 125 goto FAIL0; 126 } 127 128 parms->tid = thread; 129 parms->start = start; 130 parms->arg = arg; 131 132 #if defined(HAVE_SIGSET_T) 133 134 /* 135 * Threads inherit their initial sigmask from their creator thread. 136 */ 137 self = pthread_self(); 138 tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask; 139 140 #endif /* HAVE_SIGSET_T */ 141 142 143 if (a != NULL) 144 { 145 stackSize = (unsigned int)a->stacksize; 146 tp->detachState = a->detachstate; 147 priority = a->param.sched_priority; 148 149 #if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) 150 /* WinCE */ 151 #else 152 /* Everything else */ 153 154 /* 155 * Thread priority must be set to a valid system level 156 * without altering the value set by pthread_attr_setschedparam(). 157 */ 158 159 /* 160 * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads 161 * don't inherit their creator's priority. They are started with 162 * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying 163 * an 'attr' arg to pthread_create() is equivalent to defaulting to 164 * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL. 165 */ 166 if (PTHREAD_INHERIT_SCHED == a->inheritsched) 167 { 168 /* 169 * If the thread that called pthread_create() is a Win32 thread 170 * then the inherited priority could be the result of a temporary 171 * system adjustment. This is not the case for POSIX threads. 172 */ 173 #if ! defined(HAVE_SIGSET_T) 174 self = pthread_self (); 175 #endif 176 priority = ((ptw32_thread_t *) self.p)->sched_priority; 177 } 178 179 #endif 180 181 } 182 else 183 { 184 /* 185 * Default stackSize 186 */ 187 stackSize = PTHREAD_STACK_MIN; 188 } 189 190 tp->state = run ? PThreadStateInitial : PThreadStateSuspended; 191 192 tp->keys = NULL; 193 194 /* 195 * Threads must be started in suspended mode and resumed if necessary 196 * after _beginthreadex returns us the handle. Otherwise we set up a 197 * race condition between the creating and the created threads. 198 * Note that we also retain a local copy of the handle for use 199 * by us in case thread.p->threadH gets NULLed later but before we've 200 * finished with it here. 201 */ 202 203 #if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__) 204 205 tp->threadH = 206 threadH = 207 (HANDLE) _beginthreadex ((void *) NULL, /* No security info */ 208 stackSize, /* default stack size */ 209 ptw32_threadStart, 210 parms, 211 (unsigned) 212 CREATE_SUSPENDED, 213 (unsigned *) &(tp->thread)); 214 215 if (threadH != 0) 216 { 217 if (a != NULL) 218 { 219 (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); 220 } 221 222 if (run) 223 { 224 ResumeThread (threadH); 225 } 226 } 227 228 #else 229 230 { 231 ptw32_mcs_local_node_t stateLock; 232 233 /* 234 * This lock will force pthread_threadStart() to wait until we have 235 * the thread handle and have set the priority. 236 */ 237 ptw32_mcs_lock_acquire(&tp->stateLock, &stateLock); 238 239 tp->threadH = 240 threadH = 241 (HANDLE) _beginthread (ptw32_threadStart, stackSize, /* default stack size */ 242 parms); 243 244 /* 245 * Make the return code match _beginthreadex's. 246 */ 247 if (threadH == (HANDLE) - 1L) 248 { 249 tp->threadH = threadH = 0; 250 } 251 else 252 { 253 if (!run) 254 { 255 /* 256 * beginthread does not allow for create flags, so we do it now. 257 * Note that beginthread itself creates the thread in SUSPENDED 258 * mode, and then calls ResumeThread to start it. 259 */ 260 SuspendThread (threadH); 261 } 262 263 if (a != NULL) 264 { 265 (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); 266 } 267 } 268 269 ptw32_mcs_lock_release (&stateLock); 270 } 271 #endif 272 273 result = (threadH != 0) ? 0 : EAGAIN; 274 275 /* 276 * Fall Through Intentionally 277 */ 278 279 /* 280 * ------------ 281 * Failure Code 282 * ------------ 283 */ 284 285 FAIL0: 286 if (result != 0) 287 { 288 289 ptw32_threadDestroy (thread); 290 tp = NULL; 291 292 if (parms != NULL) 293 { 294 free (parms); 295 } 296 } 297 else 298 { 299 *tid = thread; 300 } 301 302 #if defined(_UWIN) 303 if (result == 0) 304 pthread_count++; 305 #endif 306 return (result); 307 308 } /* pthread_create */ 309