1 2 /* Posix threads interface */ 3 4 #include <stdlib.h> 5 #include <string.h> 6 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) 7 #define destructor xxdestructor 8 #endif 9 #include <pthread.h> 10 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) 11 #undef destructor 12 #endif 13 #include <signal.h> 14 15 /* The POSIX spec requires that use of pthread_attr_setstacksize 16 be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */ 17 #ifdef _POSIX_THREAD_ATTR_STACKSIZE 18 #ifndef THREAD_STACK_SIZE 19 #define THREAD_STACK_SIZE 0 /* use default stack size */ 20 #endif 21 22 #if (defined(__APPLE__) || defined(__FreeBSD__)) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 23 /* The default stack size for new threads on OSX is small enough that 24 * we'll get hard crashes instead of 'maximum recursion depth exceeded' 25 * exceptions. 26 * 27 * The default stack size below is the minimal stack size where a 28 * simple recursive function doesn't cause a hard crash. 29 */ 30 #undef THREAD_STACK_SIZE 31 #define THREAD_STACK_SIZE 0x400000 32 #endif 33 /* for safety, ensure a viable minimum stacksize */ 34 #define THREAD_STACK_MIN 0x8000 /* 32kB */ 35 #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ 36 #ifdef THREAD_STACK_SIZE 37 #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined" 38 #endif 39 #endif 40 41 /* The POSIX spec says that implementations supporting the sem_* 42 family of functions must indicate this by defining 43 _POSIX_SEMAPHORES. */ 44 #ifdef _POSIX_SEMAPHORES 45 /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so 46 we need to add 0 to make it work there as well. */ 47 #if (_POSIX_SEMAPHORES+0) == -1 48 #define HAVE_BROKEN_POSIX_SEMAPHORES 49 #else 50 #include <semaphore.h> 51 #include <errno.h> 52 #endif 53 #endif 54 55 /* Before FreeBSD 5.4, system scope threads was very limited resource 56 in default setting. So the process scope is preferred to get 57 enough number of threads to work. */ 58 #ifdef __FreeBSD__ 59 #include <osreldate.h> 60 #if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101 61 #undef PTHREAD_SYSTEM_SCHED_SUPPORTED 62 #endif 63 #endif 64 65 #if !defined(pthread_attr_default) 66 # define pthread_attr_default ((pthread_attr_t *)NULL) 67 #endif 68 #if !defined(pthread_mutexattr_default) 69 # define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL) 70 #endif 71 #if !defined(pthread_condattr_default) 72 # define pthread_condattr_default ((pthread_condattr_t *)NULL) 73 #endif 74 75 76 /* Whether or not to use semaphores directly rather than emulating them with 77 * mutexes and condition variables: 78 */ 79 #if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) 80 # define USE_SEMAPHORES 81 #else 82 # undef USE_SEMAPHORES 83 #endif 84 85 86 /* On platforms that don't use standard POSIX threads pthread_sigmask() 87 * isn't present. DEC threads uses sigprocmask() instead as do most 88 * other UNIX International compliant systems that don't have the full 89 * pthread implementation. 90 */ 91 #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) 92 # define SET_THREAD_SIGMASK pthread_sigmask 93 #else 94 # define SET_THREAD_SIGMASK sigprocmask 95 #endif 96 97 98 /* A pthread mutex isn't sufficient to model the Python lock type 99 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the 100 * following are undefined: 101 * -> a thread tries to lock a mutex it already has locked 102 * -> a thread tries to unlock a mutex locked by a different thread 103 * pthread mutexes are designed for serializing threads over short pieces 104 * of code anyway, so wouldn't be an appropriate implementation of 105 * Python's locks regardless. 106 * 107 * The pthread_lock struct implements a Python lock as a "locked?" bit 108 * and a <condition, mutex> pair. In general, if the bit can be acquired 109 * instantly, it is, else the pair is used to block the thread until the 110 * bit is cleared. 9 May 1994 tim (at) ksr.com 111 */ 112 113 typedef struct { 114 char locked; /* 0=unlocked, 1=locked */ 115 /* a <cond, mutex> pair to handle an acquire of a locked lock */ 116 pthread_cond_t lock_released; 117 pthread_mutex_t mut; 118 } pthread_lock; 119 120 #define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; } 121 122 /* 123 * Initialization. 124 */ 125 126 #ifdef _HAVE_BSDI 127 static 128 void _noop(void) 129 { 130 } 131 132 static void 133 PyThread__init_thread(void) 134 { 135 /* DO AN INIT BY STARTING THE THREAD */ 136 static int dummy = 0; 137 pthread_t thread1; 138 pthread_create(&thread1, NULL, (void *) _noop, &dummy); 139 pthread_join(thread1, NULL); 140 } 141 142 #else /* !_HAVE_BSDI */ 143 144 static void 145 PyThread__init_thread(void) 146 { 147 #if defined(_AIX) && defined(__GNUC__) 148 pthread_init(); 149 #endif 150 } 151 152 #endif /* !_HAVE_BSDI */ 153 154 /* 155 * Thread support. 156 */ 157 158 159 long 160 PyThread_start_new_thread(void (*func)(void *), void *arg) 161 { 162 pthread_t th; 163 int status; 164 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 165 pthread_attr_t attrs; 166 #endif 167 #if defined(THREAD_STACK_SIZE) 168 size_t tss; 169 #endif 170 171 dprintf(("PyThread_start_new_thread called\n")); 172 if (!initialized) 173 PyThread_init_thread(); 174 175 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 176 if (pthread_attr_init(&attrs) != 0) 177 return -1; 178 #endif 179 #if defined(THREAD_STACK_SIZE) 180 tss = (_pythread_stacksize != 0) ? _pythread_stacksize 181 : THREAD_STACK_SIZE; 182 if (tss != 0) { 183 if (pthread_attr_setstacksize(&attrs, tss) != 0) { 184 pthread_attr_destroy(&attrs); 185 return -1; 186 } 187 } 188 #endif 189 #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 190 pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); 191 #endif 192 193 status = pthread_create(&th, 194 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 195 &attrs, 196 #else 197 (pthread_attr_t*)NULL, 198 #endif 199 (void* (*)(void *))func, 200 (void *)arg 201 ); 202 203 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 204 pthread_attr_destroy(&attrs); 205 #endif 206 if (status != 0) 207 return -1; 208 209 pthread_detach(th); 210 211 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG 212 return (long) th; 213 #else 214 return (long) *(long *) &th; 215 #endif 216 } 217 218 /* XXX This implementation is considered (to quote Tim Peters) "inherently 219 hosed" because: 220 - It does not guarantee the promise that a non-zero integer is returned. 221 - The cast to long is inherently unsafe. 222 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the 223 latter return statement (for Alpha OSF/1) are any longer necessary. 224 */ 225 long 226 PyThread_get_thread_ident(void) 227 { 228 volatile pthread_t threadid; 229 if (!initialized) 230 PyThread_init_thread(); 231 /* Jump through some hoops for Alpha OSF/1 */ 232 threadid = pthread_self(); 233 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG 234 return (long) threadid; 235 #else 236 return (long) *(long *) &threadid; 237 #endif 238 } 239 240 void 241 PyThread_exit_thread(void) 242 { 243 dprintf(("PyThread_exit_thread called\n")); 244 if (!initialized) { 245 exit(0); 246 } 247 } 248 249 #ifdef USE_SEMAPHORES 250 251 /* 252 * Lock support. 253 */ 254 255 PyThread_type_lock 256 PyThread_allocate_lock(void) 257 { 258 sem_t *lock; 259 int status, error = 0; 260 261 dprintf(("PyThread_allocate_lock called\n")); 262 if (!initialized) 263 PyThread_init_thread(); 264 265 lock = (sem_t *)malloc(sizeof(sem_t)); 266 267 if (lock) { 268 status = sem_init(lock,0,1); 269 CHECK_STATUS("sem_init"); 270 271 if (error) { 272 free((void *)lock); 273 lock = NULL; 274 } 275 } 276 277 dprintf(("PyThread_allocate_lock() -> %p\n", lock)); 278 return (PyThread_type_lock)lock; 279 } 280 281 void 282 PyThread_free_lock(PyThread_type_lock lock) 283 { 284 sem_t *thelock = (sem_t *)lock; 285 int status, error = 0; 286 287 dprintf(("PyThread_free_lock(%p) called\n", lock)); 288 289 if (!thelock) 290 return; 291 292 status = sem_destroy(thelock); 293 CHECK_STATUS("sem_destroy"); 294 295 free((void *)thelock); 296 } 297 298 /* 299 * As of February 2002, Cygwin thread implementations mistakenly report error 300 * codes in the return value of the sem_ calls (like the pthread_ functions). 301 * Correct implementations return -1 and put the code in errno. This supports 302 * either. 303 */ 304 static int 305 fix_status(int status) 306 { 307 return (status == -1) ? errno : status; 308 } 309 310 int 311 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) 312 { 313 int success; 314 sem_t *thelock = (sem_t *)lock; 315 int status, error = 0; 316 317 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); 318 319 do { 320 if (waitflag) 321 status = fix_status(sem_wait(thelock)); 322 else 323 status = fix_status(sem_trywait(thelock)); 324 } while (status == EINTR); /* Retry if interrupted by a signal */ 325 326 if (waitflag) { 327 CHECK_STATUS("sem_wait"); 328 } else if (status != EAGAIN) { 329 CHECK_STATUS("sem_trywait"); 330 } 331 332 success = (status == 0) ? 1 : 0; 333 334 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); 335 return success; 336 } 337 338 void 339 PyThread_release_lock(PyThread_type_lock lock) 340 { 341 sem_t *thelock = (sem_t *)lock; 342 int status, error = 0; 343 344 dprintf(("PyThread_release_lock(%p) called\n", lock)); 345 346 status = sem_post(thelock); 347 CHECK_STATUS("sem_post"); 348 } 349 350 #else /* USE_SEMAPHORES */ 351 352 /* 353 * Lock support. 354 */ 355 PyThread_type_lock 356 PyThread_allocate_lock(void) 357 { 358 pthread_lock *lock; 359 int status, error = 0; 360 361 dprintf(("PyThread_allocate_lock called\n")); 362 if (!initialized) 363 PyThread_init_thread(); 364 365 lock = (pthread_lock *) malloc(sizeof(pthread_lock)); 366 if (lock) { 367 memset((void *)lock, '\0', sizeof(pthread_lock)); 368 lock->locked = 0; 369 370 status = pthread_mutex_init(&lock->mut, 371 pthread_mutexattr_default); 372 CHECK_STATUS("pthread_mutex_init"); 373 374 status = pthread_cond_init(&lock->lock_released, 375 pthread_condattr_default); 376 CHECK_STATUS("pthread_cond_init"); 377 378 if (error) { 379 free((void *)lock); 380 lock = 0; 381 } 382 } 383 384 dprintf(("PyThread_allocate_lock() -> %p\n", lock)); 385 return (PyThread_type_lock) lock; 386 } 387 388 void 389 PyThread_free_lock(PyThread_type_lock lock) 390 { 391 pthread_lock *thelock = (pthread_lock *)lock; 392 int status, error = 0; 393 394 dprintf(("PyThread_free_lock(%p) called\n", lock)); 395 396 status = pthread_mutex_destroy( &thelock->mut ); 397 CHECK_STATUS("pthread_mutex_destroy"); 398 399 status = pthread_cond_destroy( &thelock->lock_released ); 400 CHECK_STATUS("pthread_cond_destroy"); 401 402 free((void *)thelock); 403 } 404 405 int 406 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) 407 { 408 int success; 409 pthread_lock *thelock = (pthread_lock *)lock; 410 int status, error = 0; 411 412 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); 413 414 status = pthread_mutex_lock( &thelock->mut ); 415 CHECK_STATUS("pthread_mutex_lock[1]"); 416 success = thelock->locked == 0; 417 418 if ( !success && waitflag ) { 419 /* continue trying until we get the lock */ 420 421 /* mut must be locked by me -- part of the condition 422 * protocol */ 423 while ( thelock->locked ) { 424 status = pthread_cond_wait(&thelock->lock_released, 425 &thelock->mut); 426 CHECK_STATUS("pthread_cond_wait"); 427 } 428 success = 1; 429 } 430 if (success) thelock->locked = 1; 431 status = pthread_mutex_unlock( &thelock->mut ); 432 CHECK_STATUS("pthread_mutex_unlock[1]"); 433 434 if (error) success = 0; 435 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); 436 return success; 437 } 438 439 void 440 PyThread_release_lock(PyThread_type_lock lock) 441 { 442 pthread_lock *thelock = (pthread_lock *)lock; 443 int status, error = 0; 444 445 dprintf(("PyThread_release_lock(%p) called\n", lock)); 446 447 status = pthread_mutex_lock( &thelock->mut ); 448 CHECK_STATUS("pthread_mutex_lock[3]"); 449 450 thelock->locked = 0; 451 452 status = pthread_mutex_unlock( &thelock->mut ); 453 CHECK_STATUS("pthread_mutex_unlock[3]"); 454 455 /* wake up someone (anyone, if any) waiting on the lock */ 456 status = pthread_cond_signal( &thelock->lock_released ); 457 CHECK_STATUS("pthread_cond_signal"); 458 } 459 460 #endif /* USE_SEMAPHORES */ 461 462 /* set the thread stack size. 463 * Return 0 if size is valid, -1 if size is invalid, 464 * -2 if setting stack size is not supported. 465 */ 466 static int 467 _pythread_pthread_set_stacksize(size_t size) 468 { 469 #if defined(THREAD_STACK_SIZE) 470 pthread_attr_t attrs; 471 size_t tss_min; 472 int rc = 0; 473 #endif 474 475 /* set to default */ 476 if (size == 0) { 477 _pythread_stacksize = 0; 478 return 0; 479 } 480 481 #if defined(THREAD_STACK_SIZE) 482 #if defined(PTHREAD_STACK_MIN) 483 tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN 484 : THREAD_STACK_MIN; 485 #else 486 tss_min = THREAD_STACK_MIN; 487 #endif 488 if (size >= tss_min) { 489 /* validate stack size by setting thread attribute */ 490 if (pthread_attr_init(&attrs) == 0) { 491 rc = pthread_attr_setstacksize(&attrs, size); 492 pthread_attr_destroy(&attrs); 493 if (rc == 0) { 494 _pythread_stacksize = size; 495 return 0; 496 } 497 } 498 } 499 return -1; 500 #else 501 return -2; 502 #endif 503 } 504 505 #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) 506