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 extern void pthread_init(void); 149 pthread_init(); 150 #endif 151 } 152 153 #endif /* !_HAVE_BSDI */ 154 155 /* 156 * Thread support. 157 */ 158 159 160 long 161 PyThread_start_new_thread(void (*func)(void *), void *arg) 162 { 163 pthread_t th; 164 int status; 165 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 166 pthread_attr_t attrs; 167 #endif 168 #if defined(THREAD_STACK_SIZE) 169 size_t tss; 170 #endif 171 172 dprintf(("PyThread_start_new_thread called\n")); 173 if (!initialized) 174 PyThread_init_thread(); 175 176 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 177 if (pthread_attr_init(&attrs) != 0) 178 return -1; 179 #endif 180 #if defined(THREAD_STACK_SIZE) 181 tss = (_pythread_stacksize != 0) ? _pythread_stacksize 182 : THREAD_STACK_SIZE; 183 if (tss != 0) { 184 if (pthread_attr_setstacksize(&attrs, tss) != 0) { 185 pthread_attr_destroy(&attrs); 186 return -1; 187 } 188 } 189 #endif 190 #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 191 pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); 192 #endif 193 194 status = pthread_create(&th, 195 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 196 &attrs, 197 #else 198 (pthread_attr_t*)NULL, 199 #endif 200 (void* (*)(void *))func, 201 (void *)arg 202 ); 203 204 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) 205 pthread_attr_destroy(&attrs); 206 #endif 207 if (status != 0) 208 return -1; 209 210 pthread_detach(th); 211 212 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG 213 return (long) th; 214 #else 215 return (long) *(long *) &th; 216 #endif 217 } 218 219 /* XXX This implementation is considered (to quote Tim Peters) "inherently 220 hosed" because: 221 - It does not guarantee the promise that a non-zero integer is returned. 222 - The cast to long is inherently unsafe. 223 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the 224 latter return statement (for Alpha OSF/1) are any longer necessary. 225 */ 226 long 227 PyThread_get_thread_ident(void) 228 { 229 volatile pthread_t threadid; 230 if (!initialized) 231 PyThread_init_thread(); 232 /* Jump through some hoops for Alpha OSF/1 */ 233 threadid = pthread_self(); 234 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG 235 return (long) threadid; 236 #else 237 return (long) *(long *) &threadid; 238 #endif 239 } 240 241 void 242 PyThread_exit_thread(void) 243 { 244 dprintf(("PyThread_exit_thread called\n")); 245 if (!initialized) { 246 exit(0); 247 } 248 } 249 250 #ifdef USE_SEMAPHORES 251 252 /* 253 * Lock support. 254 */ 255 256 PyThread_type_lock 257 PyThread_allocate_lock(void) 258 { 259 sem_t *lock; 260 int status, error = 0; 261 262 dprintf(("PyThread_allocate_lock called\n")); 263 if (!initialized) 264 PyThread_init_thread(); 265 266 lock = (sem_t *)malloc(sizeof(sem_t)); 267 268 if (lock) { 269 status = sem_init(lock,0,1); 270 CHECK_STATUS("sem_init"); 271 272 if (error) { 273 free((void *)lock); 274 lock = NULL; 275 } 276 } 277 278 dprintf(("PyThread_allocate_lock() -> %p\n", lock)); 279 return (PyThread_type_lock)lock; 280 } 281 282 void 283 PyThread_free_lock(PyThread_type_lock lock) 284 { 285 sem_t *thelock = (sem_t *)lock; 286 int status, error = 0; 287 288 (void) error; /* silence unused-but-set-variable warning */ 289 dprintf(("PyThread_free_lock(%p) called\n", lock)); 290 291 if (!thelock) 292 return; 293 294 status = sem_destroy(thelock); 295 CHECK_STATUS("sem_destroy"); 296 297 free((void *)thelock); 298 } 299 300 /* 301 * As of February 2002, Cygwin thread implementations mistakenly report error 302 * codes in the return value of the sem_ calls (like the pthread_ functions). 303 * Correct implementations return -1 and put the code in errno. This supports 304 * either. 305 */ 306 static int 307 fix_status(int status) 308 { 309 return (status == -1) ? errno : status; 310 } 311 312 int 313 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) 314 { 315 int success; 316 sem_t *thelock = (sem_t *)lock; 317 int status, error = 0; 318 319 (void) error; /* silence unused-but-set-variable warning */ 320 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); 321 322 do { 323 if (waitflag) 324 status = fix_status(sem_wait(thelock)); 325 else 326 status = fix_status(sem_trywait(thelock)); 327 } while (status == EINTR); /* Retry if interrupted by a signal */ 328 329 if (waitflag) { 330 CHECK_STATUS("sem_wait"); 331 } else if (status != EAGAIN) { 332 CHECK_STATUS("sem_trywait"); 333 } 334 335 success = (status == 0) ? 1 : 0; 336 337 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); 338 return success; 339 } 340 341 void 342 PyThread_release_lock(PyThread_type_lock lock) 343 { 344 sem_t *thelock = (sem_t *)lock; 345 int status, error = 0; 346 347 (void) error; /* silence unused-but-set-variable warning */ 348 dprintf(("PyThread_release_lock(%p) called\n", lock)); 349 350 status = sem_post(thelock); 351 CHECK_STATUS("sem_post"); 352 } 353 354 #else /* USE_SEMAPHORES */ 355 356 /* 357 * Lock support. 358 */ 359 PyThread_type_lock 360 PyThread_allocate_lock(void) 361 { 362 pthread_lock *lock; 363 int status, error = 0; 364 365 dprintf(("PyThread_allocate_lock called\n")); 366 if (!initialized) 367 PyThread_init_thread(); 368 369 lock = (pthread_lock *) malloc(sizeof(pthread_lock)); 370 if (lock) { 371 memset((void *)lock, '\0', sizeof(pthread_lock)); 372 lock->locked = 0; 373 374 status = pthread_mutex_init(&lock->mut, 375 pthread_mutexattr_default); 376 CHECK_STATUS("pthread_mutex_init"); 377 378 status = pthread_cond_init(&lock->lock_released, 379 pthread_condattr_default); 380 CHECK_STATUS("pthread_cond_init"); 381 382 if (error) { 383 free((void *)lock); 384 lock = 0; 385 } 386 } 387 388 dprintf(("PyThread_allocate_lock() -> %p\n", lock)); 389 return (PyThread_type_lock) lock; 390 } 391 392 void 393 PyThread_free_lock(PyThread_type_lock lock) 394 { 395 pthread_lock *thelock = (pthread_lock *)lock; 396 int status, error = 0; 397 398 (void) error; /* silence unused-but-set-variable warning */ 399 dprintf(("PyThread_free_lock(%p) called\n", lock)); 400 401 status = pthread_mutex_destroy( &thelock->mut ); 402 CHECK_STATUS("pthread_mutex_destroy"); 403 404 status = pthread_cond_destroy( &thelock->lock_released ); 405 CHECK_STATUS("pthread_cond_destroy"); 406 407 free((void *)thelock); 408 } 409 410 int 411 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) 412 { 413 int success; 414 pthread_lock *thelock = (pthread_lock *)lock; 415 int status, error = 0; 416 417 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); 418 419 status = pthread_mutex_lock( &thelock->mut ); 420 CHECK_STATUS("pthread_mutex_lock[1]"); 421 success = thelock->locked == 0; 422 423 if ( !success && waitflag ) { 424 /* continue trying until we get the lock */ 425 426 /* mut must be locked by me -- part of the condition 427 * protocol */ 428 while ( thelock->locked ) { 429 status = pthread_cond_wait(&thelock->lock_released, 430 &thelock->mut); 431 CHECK_STATUS("pthread_cond_wait"); 432 } 433 success = 1; 434 } 435 if (success) thelock->locked = 1; 436 status = pthread_mutex_unlock( &thelock->mut ); 437 CHECK_STATUS("pthread_mutex_unlock[1]"); 438 439 if (error) success = 0; 440 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); 441 return success; 442 } 443 444 void 445 PyThread_release_lock(PyThread_type_lock lock) 446 { 447 pthread_lock *thelock = (pthread_lock *)lock; 448 int status, error = 0; 449 450 (void) error; /* silence unused-but-set-variable warning */ 451 dprintf(("PyThread_release_lock(%p) called\n", lock)); 452 453 status = pthread_mutex_lock( &thelock->mut ); 454 CHECK_STATUS("pthread_mutex_lock[3]"); 455 456 thelock->locked = 0; 457 458 status = pthread_mutex_unlock( &thelock->mut ); 459 CHECK_STATUS("pthread_mutex_unlock[3]"); 460 461 /* wake up someone (anyone, if any) waiting on the lock */ 462 status = pthread_cond_signal( &thelock->lock_released ); 463 CHECK_STATUS("pthread_cond_signal"); 464 } 465 466 #endif /* USE_SEMAPHORES */ 467 468 /* set the thread stack size. 469 * Return 0 if size is valid, -1 if size is invalid, 470 * -2 if setting stack size is not supported. 471 */ 472 static int 473 _pythread_pthread_set_stacksize(size_t size) 474 { 475 #if defined(THREAD_STACK_SIZE) 476 pthread_attr_t attrs; 477 size_t tss_min; 478 int rc = 0; 479 #endif 480 481 /* set to default */ 482 if (size == 0) { 483 _pythread_stacksize = 0; 484 return 0; 485 } 486 487 #if defined(THREAD_STACK_SIZE) 488 #if defined(PTHREAD_STACK_MIN) 489 tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN 490 : THREAD_STACK_MIN; 491 #else 492 tss_min = THREAD_STACK_MIN; 493 #endif 494 if (size >= tss_min) { 495 /* validate stack size by setting thread attribute */ 496 if (pthread_attr_init(&attrs) == 0) { 497 rc = pthread_attr_setstacksize(&attrs, size); 498 pthread_attr_destroy(&attrs); 499 if (rc == 0) { 500 _pythread_stacksize = size; 501 return 0; 502 } 503 } 504 } 505 return -1; 506 #else 507 return -2; 508 #endif 509 } 510 511 #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) 512