thread_pthread.h 17.4 KB
Newer Older
1

2 3 4
/* Posix threads interface */

#include <stdlib.h>
5
#include <string.h>
6
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
7 8
#define destructor xxdestructor
#endif
9
#include <pthread.h>
10
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
11 12
#undef destructor
#endif
13
#include <signal.h>
14

15 16 17 18
/* The POSIX spec requires that use of pthread_attr_setstacksize
   be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
#ifndef THREAD_STACK_SIZE
19
#define THREAD_STACK_SIZE       0       /* use default stack size */
20
#endif
21

22 23 24 25 26 27 28 29 30 31 32 33
/* The default stack size for new threads on OSX and BSD is small enough that
 * we'll get hard crashes instead of 'maximum recursion depth exceeded'
 * exceptions.
 *
 * The default stack sizes below are the empirically determined minimal stack
 * sizes where a simple recursive function doesn't cause a hard crash.
 */
#if defined(__APPLE__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
#undef  THREAD_STACK_SIZE
#define THREAD_STACK_SIZE       0x500000
#endif
#if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
34 35 36
#undef  THREAD_STACK_SIZE
#define THREAD_STACK_SIZE       0x400000
#endif
37
/* for safety, ensure a viable minimum stacksize */
38
#define THREAD_STACK_MIN        0x8000  /* 32kB */
39 40 41 42 43 44
#else  /* !_POSIX_THREAD_ATTR_STACKSIZE */
#ifdef THREAD_STACK_SIZE
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
#endif
#endif

45 46
/* The POSIX spec says that implementations supporting the sem_*
   family of functions must indicate this by defining
47
   _POSIX_SEMAPHORES. */
48
#ifdef _POSIX_SEMAPHORES
49
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
50 51
   we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
52 53
#define HAVE_BROKEN_POSIX_SEMAPHORES
#else
54 55 56
#include <semaphore.h>
#include <errno.h>
#endif
57
#endif
58

59 60 61 62 63 64 65 66 67 68
/* Before FreeBSD 5.4, system scope threads was very limited resource
   in default setting.  So the process scope is preferred to get
   enough number of threads to work. */
#ifdef __FreeBSD__
#include <osreldate.h>
#if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101
#undef PTHREAD_SYSTEM_SCHED_SUPPORTED
#endif
#endif

69
#if !defined(pthread_attr_default)
70
#  define pthread_attr_default ((pthread_attr_t *)NULL)
71 72
#endif
#if !defined(pthread_mutexattr_default)
73
#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
74 75
#endif
#if !defined(pthread_condattr_default)
76
#  define pthread_condattr_default ((pthread_condattr_t *)NULL)
77
#endif
78

79

80 81 82
/* Whether or not to use semaphores directly rather than emulating them with
 * mutexes and condition variables:
 */
83 84
#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \
     defined(HAVE_SEM_TIMEDWAIT))
85 86 87 88 89 90
#  define USE_SEMAPHORES
#else
#  undef USE_SEMAPHORES
#endif


91 92 93 94 95
/* On platforms that don't use standard POSIX threads pthread_sigmask()
 * isn't present.  DEC threads uses sigprocmask() instead as do most
 * other UNIX International compliant systems that don't have the full
 * pthread implementation.
 */
96
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
97 98 99 100 101 102
#  define SET_THREAD_SIGMASK pthread_sigmask
#else
#  define SET_THREAD_SIGMASK sigprocmask
#endif


103 104 105 106 107 108 109 110 111
/* We assume all modern POSIX systems have gettimeofday() */
#ifdef GETTIMEOFDAY_NO_TZ
#define GETTIMEOFDAY(ptv) gettimeofday(ptv)
#else
#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
#endif

#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \
do { \
112 113 114 115 116 117 118 119
    struct timeval tv; \
    GETTIMEOFDAY(&tv); \
    tv.tv_usec += microseconds % 1000000; \
    tv.tv_sec += microseconds / 1000000; \
    tv.tv_sec += tv.tv_usec / 1000000; \
    tv.tv_usec %= 1000000; \
    ts.tv_sec = tv.tv_sec; \
    ts.tv_nsec = tv.tv_usec * 1000; \
120 121 122
} while(0)


123 124 125 126 127 128 129
/* A pthread mutex isn't sufficient to model the Python lock type
 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
 * following are undefined:
 *  -> a thread tries to lock a mutex it already has locked
 *  -> a thread tries to unlock a mutex locked by a different thread
 * pthread mutexes are designed for serializing threads over short pieces
 * of code anyway, so wouldn't be an appropriate implementation of
130
 * Python's locks regardless.
131 132 133 134 135
 *
 * The pthread_lock struct implements a Python lock as a "locked?" bit
 * and a <condition, mutex> pair.  In general, if the bit can be acquired
 * instantly, it is, else the pair is used to block the thread until the
 * bit is cleared.     9 May 1994 tim@ksr.com
136
 */
137

138
typedef struct {
139 140 141 142
    char             locked; /* 0=unlocked, 1=locked */
    /* a <cond, mutex> pair to handle an acquire of a locked lock */
    pthread_cond_t   lock_released;
    pthread_mutex_t  mut;
143 144
} pthread_lock;

145
#define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
146

147 148 149
/*
 * Initialization.
 */
150

151
#if defined(_HAVE_BSDI)
152 153
static
void _noop(void)
154 155 156
{
}

157 158
static void
PyThread__init_thread(void)
159
{
160 161 162 163 164
    /* DO AN INIT BY STARTING THE THREAD */
    static int dummy = 0;
    pthread_t thread1;
    pthread_create(&thread1, NULL, (void *) _noop, &dummy);
    pthread_join(thread1, NULL);
165 166 167 168
}

#else /* !_HAVE_BSDI */

169 170
static void
PyThread__init_thread(void)
171
{
172
#if defined(_AIX) && defined(__GNUC__)
173
    extern void pthread_init(void);
174
    pthread_init();
175
#endif
176 177
}

178 179
#endif /* !_HAVE_BSDI */

180 181 182
/*
 * Thread support.
 */
183 184


185
long
186
PyThread_start_new_thread(void (*func)(void *), void *arg)
187
{
188 189
    pthread_t th;
    int status;
190
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
191
    pthread_attr_t attrs;
192
#endif
193
#if defined(THREAD_STACK_SIZE)
194
    size_t      tss;
195 196
#endif

197 198 199
    dprintf(("PyThread_start_new_thread called\n"));
    if (!initialized)
        PyThread_init_thread();
200

201
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
202 203
    if (pthread_attr_init(&attrs) != 0)
        return -1;
204
#endif
205
#if defined(THREAD_STACK_SIZE)
206 207 208 209 210 211 212 213
    tss = (_pythread_stacksize != 0) ? _pythread_stacksize
                                     : THREAD_STACK_SIZE;
    if (tss != 0) {
        if (pthread_attr_setstacksize(&attrs, tss) != 0) {
            pthread_attr_destroy(&attrs);
            return -1;
        }
    }
214
#endif
215
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
216
    pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
217
#endif
218

219
    status = pthread_create(&th,
220
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
221
                             &attrs,
222
#else
223
                             (pthread_attr_t*)NULL,
224
#endif
225 226 227
                             (void* (*)(void *))func,
                             (void *)arg
                             );
228

229
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
230
    pthread_attr_destroy(&attrs);
231
#endif
232 233
    if (status != 0)
        return -1;
234

235
    pthread_detach(th);
236

237
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
238
    return (long) th;
239
#else
240
    return (long) *(long *) &th;
241
#endif
242 243
}

244 245
/* XXX This implementation is considered (to quote Tim Peters) "inherently
   hosed" because:
Skip Montanaro's avatar
Skip Montanaro committed
246
     - It does not guarantee the promise that a non-zero integer is returned.
247
     - The cast to long is inherently unsafe.
248
     - It is not clear that the 'volatile' (for AIX?) are any longer necessary.
249
*/
250
long
251
PyThread_get_thread_ident(void)
252
{
253 254 255 256 257
    volatile pthread_t threadid;
    if (!initialized)
        PyThread_init_thread();
    threadid = pthread_self();
    return (long) threadid;
258 259
}

260
void
261
PyThread_exit_thread(void)
262
{
263
    dprintf(("PyThread_exit_thread called\n"));
264
    if (!initialized)
265
        exit(0);
266
    pthread_exit(0);
267 268
}

269 270 271 272 273 274
#ifdef USE_SEMAPHORES

/*
 * Lock support.
 */

275
PyThread_type_lock
276 277
PyThread_allocate_lock(void)
{
278 279
    sem_t *lock;
    int status, error = 0;
280

281 282 283
    dprintf(("PyThread_allocate_lock called\n"));
    if (!initialized)
        PyThread_init_thread();
284

285
    lock = (sem_t *)PyMem_RawMalloc(sizeof(sem_t));
286

287 288 289
    if (lock) {
        status = sem_init(lock,0,1);
        CHECK_STATUS("sem_init");
290

291
        if (error) {
292
            PyMem_RawFree((void *)lock);
293 294 295
            lock = NULL;
        }
    }
296

297 298
    dprintf(("PyThread_allocate_lock() -> %p\n", lock));
    return (PyThread_type_lock)lock;
299 300
}

301
void
302 303
PyThread_free_lock(PyThread_type_lock lock)
{
304 305
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
306

307
    (void) error; /* silence unused-but-set-variable warning */
308
    dprintf(("PyThread_free_lock(%p) called\n", lock));
309

310 311
    if (!thelock)
        return;
312

313 314
    status = sem_destroy(thelock);
    CHECK_STATUS("sem_destroy");
315

316
    PyMem_RawFree((void *)thelock);
317 318 319 320 321 322 323 324 325 326 327
}

/*
 * As of February 2002, Cygwin thread implementations mistakenly report error
 * codes in the return value of the sem_ calls (like the pthread_ functions).
 * Correct implementations return -1 and put the code in errno. This supports
 * either.
 */
static int
fix_status(int status)
{
328
    return (status == -1) ? errno : status;
329 330
}

331 332 333
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
                            int intr_flag)
334
{
335
    PyLockStatus success;
336 337 338 339
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
    struct timespec ts;

340
    (void) error; /* silence unused-but-set-variable warning */
341 342
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
343 344 345 346 347 348 349 350 351 352

    if (microseconds > 0)
        MICROSECONDS_TO_TIMESPEC(microseconds, ts);
    do {
        if (microseconds > 0)
            status = fix_status(sem_timedwait(thelock, &ts));
        else if (microseconds == 0)
            status = fix_status(sem_trywait(thelock));
        else
            status = fix_status(sem_wait(thelock));
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
        /* Retry if interrupted by a signal, unless the caller wants to be
           notified.  */
    } while (!intr_flag && status == EINTR);

    /* Don't check the status if we're stopping because of an interrupt.  */
    if (!(intr_flag && status == EINTR)) {
        if (microseconds > 0) {
            if (status != ETIMEDOUT)
                CHECK_STATUS("sem_timedwait");
        }
        else if (microseconds == 0) {
            if (status != EAGAIN)
                CHECK_STATUS("sem_trywait");
        }
        else {
            CHECK_STATUS("sem_wait");
        }
370 371
    }

372 373 374 375 376 377 378
    if (status == 0) {
        success = PY_LOCK_ACQUIRED;
    } else if (intr_flag && status == EINTR) {
        success = PY_LOCK_INTR;
    } else {
        success = PY_LOCK_FAILURE;
    }
379

380 381
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
382
    return success;
383 384
}

385
void
386 387
PyThread_release_lock(PyThread_type_lock lock)
{
388 389
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
390

391
    (void) error; /* silence unused-but-set-variable warning */
392
    dprintf(("PyThread_release_lock(%p) called\n", lock));
393

394 395
    status = sem_post(thelock);
    CHECK_STATUS("sem_post");
396 397 398 399
}

#else /* USE_SEMAPHORES */

400 401 402
/*
 * Lock support.
 */
403
PyThread_type_lock
404
PyThread_allocate_lock(void)
405
{
406 407 408 409 410 411 412
    pthread_lock *lock;
    int status, error = 0;

    dprintf(("PyThread_allocate_lock called\n"));
    if (!initialized)
        PyThread_init_thread();

413
    lock = (pthread_lock *) PyMem_RawMalloc(sizeof(pthread_lock));
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
    if (lock) {
        memset((void *)lock, '\0', sizeof(pthread_lock));
        lock->locked = 0;

        status = pthread_mutex_init(&lock->mut,
                                    pthread_mutexattr_default);
        CHECK_STATUS("pthread_mutex_init");
        /* Mark the pthread mutex underlying a Python mutex as
           pure happens-before.  We can't simply mark the
           Python-level mutex as a mutex because it can be
           acquired and released in different threads, which
           will cause errors. */
        _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);

        status = pthread_cond_init(&lock->lock_released,
                                   pthread_condattr_default);
        CHECK_STATUS("pthread_cond_init");

        if (error) {
433
            PyMem_RawFree((void *)lock);
434 435 436 437 438 439
            lock = 0;
        }
    }

    dprintf(("PyThread_allocate_lock() -> %p\n", lock));
    return (PyThread_type_lock) lock;
440 441
}

442
void
443
PyThread_free_lock(PyThread_type_lock lock)
444
{
445 446
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
447

448
    (void) error; /* silence unused-but-set-variable warning */
449
    dprintf(("PyThread_free_lock(%p) called\n", lock));
450

451 452 453
    /* some pthread-like implementations tie the mutex to the cond
     * and must have the cond destroyed first.
     */
454 455
    status = pthread_cond_destroy( &thelock->lock_released );
    CHECK_STATUS("pthread_cond_destroy");
456

457 458 459
    status = pthread_mutex_destroy( &thelock->mut );
    CHECK_STATUS("pthread_mutex_destroy");

460
    PyMem_RawFree((void *)thelock);
461 462
}

463 464 465
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
                            int intr_flag)
466
{
467
    PyLockStatus success;
468 469 470
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;

471 472
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
473 474 475 476

    status = pthread_mutex_lock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_lock[1]");

477 478 479 480 481
    if (thelock->locked == 0) {
        success = PY_LOCK_ACQUIRED;
    } else if (microseconds == 0) {
        success = PY_LOCK_FAILURE;
    } else {
482 483 484 485 486 487 488
        struct timespec ts;
        if (microseconds > 0)
            MICROSECONDS_TO_TIMESPEC(microseconds, ts);
        /* continue trying until we get the lock */

        /* mut must be locked by me -- part of the condition
         * protocol */
489 490
        success = PY_LOCK_FAILURE;
        while (success == PY_LOCK_FAILURE) {
491 492 493 494 495 496 497 498 499 500 501 502 503 504
            if (microseconds > 0) {
                status = pthread_cond_timedwait(
                    &thelock->lock_released,
                    &thelock->mut, &ts);
                if (status == ETIMEDOUT)
                    break;
                CHECK_STATUS("pthread_cond_timed_wait");
            }
            else {
                status = pthread_cond_wait(
                    &thelock->lock_released,
                    &thelock->mut);
                CHECK_STATUS("pthread_cond_wait");
            }
505 506 507 508 509 510 511 512 513 514 515 516

            if (intr_flag && status == 0 && thelock->locked) {
                /* We were woken up, but didn't get the lock.  We probably received
                 * a signal.  Return PY_LOCK_INTR to allow the caller to handle
                 * it and retry.  */
                success = PY_LOCK_INTR;
                break;
            } else if (status == 0 && !thelock->locked) {
                success = PY_LOCK_ACQUIRED;
            } else {
                success = PY_LOCK_FAILURE;
            }
517 518
        }
    }
519
    if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
520 521 522
    status = pthread_mutex_unlock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_unlock[1]");

523 524 525
    if (error) success = PY_LOCK_FAILURE;
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
526
    return success;
527 528
}

529
void
530
PyThread_release_lock(PyThread_type_lock lock)
531
{
532 533
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
534

535
    (void) error; /* silence unused-but-set-variable warning */
536
    dprintf(("PyThread_release_lock(%p) called\n", lock));
537

538 539
    status = pthread_mutex_lock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_lock[3]");
540

541
    thelock->locked = 0;
542

543 544 545
    /* wake up someone (anyone, if any) waiting on the lock */
    status = pthread_cond_signal( &thelock->lock_released );
    CHECK_STATUS("pthread_cond_signal");
546 547 548

    status = pthread_mutex_unlock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_unlock[3]");
549
}
550 551

#endif /* USE_SEMAPHORES */
552

553 554 555 556 557 558
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
    return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);
}

559 560 561 562 563 564 565 566
/* set the thread stack size.
 * Return 0 if size is valid, -1 if size is invalid,
 * -2 if setting stack size is not supported.
 */
static int
_pythread_pthread_set_stacksize(size_t size)
{
#if defined(THREAD_STACK_SIZE)
567 568 569
    pthread_attr_t attrs;
    size_t tss_min;
    int rc = 0;
570 571
#endif

572 573 574 575 576
    /* set to default */
    if (size == 0) {
        _pythread_stacksize = 0;
        return 0;
    }
577 578 579

#if defined(THREAD_STACK_SIZE)
#if defined(PTHREAD_STACK_MIN)
580 581
    tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
                                                   : THREAD_STACK_MIN;
582
#else
583
    tss_min = THREAD_STACK_MIN;
584
#endif
585 586 587 588 589 590 591 592 593 594 595 596
    if (size >= tss_min) {
        /* validate stack size by setting thread attribute */
        if (pthread_attr_init(&attrs) == 0) {
            rc = pthread_attr_setstacksize(&attrs, size);
            pthread_attr_destroy(&attrs);
            if (rc == 0) {
                _pythread_stacksize = size;
                return 0;
            }
        }
    }
    return -1;
597
#else
598
    return -2;
599 600 601
#endif
}

602
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
603 604 605 606 607 608 609 610

#define Py_HAVE_NATIVE_TLS

int
PyThread_create_key(void)
{
    pthread_key_t key;
    int fail = pthread_key_create(&key, NULL);
611 612 613 614 615 616 617 618 619
    if (fail)
        return -1;
    if (key > INT_MAX) {
        /* Issue #22206: handle integer overflow */
        pthread_key_delete(key);
        errno = ENOMEM;
        return -1;
    }
    return (int)key;
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
}

void
PyThread_delete_key(int key)
{
    pthread_key_delete(key);
}

void
PyThread_delete_key_value(int key)
{
    pthread_setspecific(key, NULL);
}

int
PyThread_set_key_value(int key, void *value)
{
    int fail;
    fail = pthread_setspecific(key, value);
    return fail ? -1 : 0;
}

void *
PyThread_get_key_value(int key)
{
    return pthread_getspecific(key);
}

void
PyThread_ReInitTLS(void)
{}