|
11 | 11 | #undef destructor |
12 | 12 | #endif |
13 | 13 | #include <signal.h> |
| 14 | +#ifdef _POSIX_SEMAPHORES |
| 15 | +#include <semaphore.h> |
| 16 | +#include <errno.h> |
| 17 | +#endif |
14 | 18 |
|
15 | 19 |
|
16 | 20 | /* try to determine what version of the Pthread Standard is installed. |
|
76 | 80 | #endif |
77 | 81 |
|
78 | 82 |
|
| 83 | +/* Whether or not to use semaphores directly rather than emulating them with |
| 84 | + * mutexes and condition variables: |
| 85 | + */ |
| 86 | +#ifdef _POSIX_SEMAPHORES |
| 87 | +# define USE_SEMAPHORES |
| 88 | +#else |
| 89 | +# undef USE_SEMAPHORES |
| 90 | +#endif |
| 91 | + |
| 92 | + |
79 | 93 | /* On platforms that don't use standard POSIX threads pthread_sigmask() |
80 | 94 | * isn't present. DEC threads uses sigprocmask() instead as do most |
81 | 95 | * other UNIX International compliant systems that don't have the full |
@@ -294,6 +308,109 @@ PyThread__exit_prog(int status) |
294 | 308 | } |
295 | 309 | #endif /* NO_EXIT_PROG */ |
296 | 310 |
|
| 311 | +#ifdef USE_SEMAPHORES |
| 312 | + |
| 313 | +/* |
| 314 | + * Lock support. |
| 315 | + */ |
| 316 | + |
| 317 | +PyThread_type_lock |
| 318 | +PyThread_allocate_lock(void) |
| 319 | +{ |
| 320 | + sem_t *lock; |
| 321 | + int status, error = 0; |
| 322 | + |
| 323 | + dprintf(("PyThread_allocate_lock called\n")); |
| 324 | + if (!initialized) |
| 325 | + PyThread_init_thread(); |
| 326 | + |
| 327 | + lock = (sem_t *)malloc(sizeof(sem_t)); |
| 328 | + |
| 329 | + if (lock) { |
| 330 | + status = sem_init(lock,0,1); |
| 331 | + CHECK_STATUS("sem_init"); |
| 332 | + |
| 333 | + if (error) { |
| 334 | + free((void *)lock); |
| 335 | + lock = NULL; |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); |
| 340 | + return (PyThread_type_lock)lock; |
| 341 | +} |
| 342 | + |
| 343 | +void |
| 344 | +PyThread_free_lock(PyThread_type_lock lock) |
| 345 | +{ |
| 346 | + sem_t *thelock = (sem_t *)lock; |
| 347 | + int status, error = 0; |
| 348 | + |
| 349 | + dprintf(("PyThread_free_lock(%p) called\n", lock)); |
| 350 | + |
| 351 | + if (!thelock) |
| 352 | + return; |
| 353 | + |
| 354 | + status = sem_destroy(thelock); |
| 355 | + CHECK_STATUS("sem_destroy"); |
| 356 | + |
| 357 | + free((void *)thelock); |
| 358 | +} |
| 359 | + |
| 360 | +/* |
| 361 | + * As of February 2002, Cygwin thread implementations mistakenly report error |
| 362 | + * codes in the return value of the sem_ calls (like the pthread_ functions). |
| 363 | + * Correct implementations return -1 and put the code in errno. This supports |
| 364 | + * either. |
| 365 | + */ |
| 366 | +static int |
| 367 | +fix_status(int status) |
| 368 | +{ |
| 369 | + return (status == -1) ? errno : status; |
| 370 | +} |
| 371 | + |
| 372 | +int |
| 373 | +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) |
| 374 | +{ |
| 375 | + int success; |
| 376 | + sem_t *thelock = (sem_t *)lock; |
| 377 | + int status, error = 0; |
| 378 | + |
| 379 | + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); |
| 380 | + |
| 381 | + do { |
| 382 | + if (waitflag) |
| 383 | + status = fix_status(sem_wait(thelock)); |
| 384 | + else |
| 385 | + status = fix_status(sem_trywait(thelock)); |
| 386 | + } while (status == EINTR); /* Retry if interrupted by a signal */ |
| 387 | + |
| 388 | + if (waitflag) { |
| 389 | + CHECK_STATUS("sem_wait"); |
| 390 | + } else if (status != EAGAIN) { |
| 391 | + CHECK_STATUS("sem_trywait"); |
| 392 | + } |
| 393 | + |
| 394 | + success = (status == 0) ? 1 : 0; |
| 395 | + |
| 396 | + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); |
| 397 | + return success; |
| 398 | +} |
| 399 | + |
| 400 | +void |
| 401 | +PyThread_release_lock(PyThread_type_lock lock) |
| 402 | +{ |
| 403 | + sem_t *thelock = (sem_t *)lock; |
| 404 | + int status, error = 0; |
| 405 | + |
| 406 | + dprintf(("PyThread_release_lock(%p) called\n", lock)); |
| 407 | + |
| 408 | + status = sem_post(thelock); |
| 409 | + CHECK_STATUS("sem_post"); |
| 410 | +} |
| 411 | + |
| 412 | +#else /* USE_SEMAPHORES */ |
| 413 | + |
297 | 414 | /* |
298 | 415 | * Lock support. |
299 | 416 | */ |
@@ -405,3 +522,5 @@ PyThread_release_lock(PyThread_type_lock lock) |
405 | 522 | status = pthread_cond_signal( &thelock->lock_released ); |
406 | 523 | CHECK_STATUS("pthread_cond_signal"); |
407 | 524 | } |
| 525 | + |
| 526 | +#endif /* USE_SEMAPHORES */ |
0 commit comments