thread_pthread.h 16.1 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 21
#endif
/* for safety, ensure a viable minimum stacksize */
22
#define THREAD_STACK_MIN        0x8000  /* 32kB */
23 24 25 26 27 28
#else  /* !_POSIX_THREAD_ATTR_STACKSIZE */
#ifdef THREAD_STACK_SIZE
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
#endif
#endif

29 30
/* The POSIX spec says that implementations supporting the sem_*
   family of functions must indicate this by defining
31
   _POSIX_SEMAPHORES. */
32
#ifdef _POSIX_SEMAPHORES
33
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
34 35
   we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
36 37
#define HAVE_BROKEN_POSIX_SEMAPHORES
#else
38 39 40
#include <semaphore.h>
#include <errno.h>
#endif
41
#endif
42

43 44 45 46 47 48 49 50 51 52
/* 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

53
#if !defined(pthread_attr_default)
54
#  define pthread_attr_default ((pthread_attr_t *)NULL)
55 56
#endif
#if !defined(pthread_mutexattr_default)
57
#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
58 59
#endif
#if !defined(pthread_condattr_default)
60
#  define pthread_condattr_default ((pthread_condattr_t *)NULL)
61
#endif
62

63

64 65 66
/* Whether or not to use semaphores directly rather than emulating them with
 * mutexes and condition variables:
 */
67 68
#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \
     defined(HAVE_SEM_TIMEDWAIT))
69 70 71 72 73 74
#  define USE_SEMAPHORES
#else
#  undef USE_SEMAPHORES
#endif


75 76 77 78 79
/* 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.
 */
80
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
81 82 83 84 85 86
#  define SET_THREAD_SIGMASK pthread_sigmask
#else
#  define SET_THREAD_SIGMASK sigprocmask
#endif


87 88 89 90 91 92 93 94 95
/* 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 { \
96 97 98 99 100 101 102 103
    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; \
104 105 106
} while(0)


107 108 109 110 111 112 113
/* 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
114
 * Python's locks regardless.
115 116 117 118 119
 *
 * 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
120
 */
121

122
typedef struct {
123 124 125 126
    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;
127 128
} pthread_lock;

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

131 132 133
/*
 * Initialization.
 */
134 135

#ifdef _HAVE_BSDI
136 137
static
void _noop(void)
138 139 140
{
}

141 142
static void
PyThread__init_thread(void)
143
{
144 145 146 147 148
    /* 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);
149 150 151 152
}

#else /* !_HAVE_BSDI */

153 154
static void
PyThread__init_thread(void)
155
{
156
#if defined(_AIX) && defined(__GNUC__)
157
    pthread_init();
158
#endif
159 160
}

161 162
#endif /* !_HAVE_BSDI */

163 164 165
/*
 * Thread support.
 */
166 167


168
long
169
PyThread_start_new_thread(void (*func)(void *), void *arg)
170
{
171 172
    pthread_t th;
    int status;
173
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
174
    pthread_attr_t attrs;
175
#endif
176
#if defined(THREAD_STACK_SIZE)
177
    size_t      tss;
178 179
#endif

180 181 182
    dprintf(("PyThread_start_new_thread called\n"));
    if (!initialized)
        PyThread_init_thread();
183

184
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
185 186
    if (pthread_attr_init(&attrs) != 0)
        return -1;
187
#endif
188
#if defined(THREAD_STACK_SIZE)
189 190 191 192 193 194 195 196
    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;
        }
    }
197
#endif
198
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
199
    pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
200
#endif
201

202
    status = pthread_create(&th,
203
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
204
                             &attrs,
205
#else
206
                             (pthread_attr_t*)NULL,
207
#endif
208 209 210
                             (void* (*)(void *))func,
                             (void *)arg
                             );
211

212
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
213
    pthread_attr_destroy(&attrs);
214
#endif
215 216
    if (status != 0)
        return -1;
217

218
    pthread_detach(th);
219

220
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
221
    return (long) th;
222
#else
223
    return (long) *(long *) &th;
224
#endif
225 226
}

227 228
/* XXX This implementation is considered (to quote Tim Peters) "inherently
   hosed" because:
Skip Montanaro's avatar
Skip Montanaro committed
229
     - It does not guarantee the promise that a non-zero integer is returned.
230
     - The cast to long is inherently unsafe.
231
     - It is not clear that the 'volatile' (for AIX?) are any longer necessary.
232
*/
233
long
234
PyThread_get_thread_ident(void)
235
{
236 237 238 239 240
    volatile pthread_t threadid;
    if (!initialized)
        PyThread_init_thread();
    threadid = pthread_self();
    return (long) threadid;
241 242
}

243
void
244
PyThread_exit_thread(void)
245
{
246
    dprintf(("PyThread_exit_thread called\n"));
247
    if (!initialized)
248
        exit(0);
249
    pthread_exit(0);
250 251
}

252 253 254 255 256 257
#ifdef USE_SEMAPHORES

/*
 * Lock support.
 */

258
PyThread_type_lock
259 260
PyThread_allocate_lock(void)
{
261 262
    sem_t *lock;
    int status, error = 0;
263

264 265 266
    dprintf(("PyThread_allocate_lock called\n"));
    if (!initialized)
        PyThread_init_thread();
267

268
    lock = (sem_t *)malloc(sizeof(sem_t));
269

270 271 272
    if (lock) {
        status = sem_init(lock,0,1);
        CHECK_STATUS("sem_init");
273

274 275 276 277 278
        if (error) {
            free((void *)lock);
            lock = NULL;
        }
    }
279

280 281
    dprintf(("PyThread_allocate_lock() -> %p\n", lock));
    return (PyThread_type_lock)lock;
282 283
}

284
void
285 286
PyThread_free_lock(PyThread_type_lock lock)
{
287 288
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
289

290
    dprintf(("PyThread_free_lock(%p) called\n", lock));
291

292 293
    if (!thelock)
        return;
294

295 296
    status = sem_destroy(thelock);
    CHECK_STATUS("sem_destroy");
297

298
    free((void *)thelock);
299 300 301 302 303 304 305 306 307 308 309
}

/*
 * 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)
{
310
    return (status == -1) ? errno : status;
311 312
}

313 314 315
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
                            int intr_flag)
316
{
317
    PyLockStatus success;
318 319 320 321
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
    struct timespec ts;

322 323
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
324 325 326 327 328 329 330 331 332 333

    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));
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
        /* 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");
        }
351 352
    }

353 354 355 356 357 358 359
    if (status == 0) {
        success = PY_LOCK_ACQUIRED;
    } else if (intr_flag && status == EINTR) {
        success = PY_LOCK_INTR;
    } else {
        success = PY_LOCK_FAILURE;
    }
360

361 362
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
363
    return success;
364 365
}

366
void
367 368
PyThread_release_lock(PyThread_type_lock lock)
{
369 370
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
371

372
    dprintf(("PyThread_release_lock(%p) called\n", lock));
373

374 375
    status = sem_post(thelock);
    CHECK_STATUS("sem_post");
376 377 378 379
}

#else /* USE_SEMAPHORES */

380 381 382
/*
 * Lock support.
 */
383
PyThread_type_lock
384
PyThread_allocate_lock(void)
385
{
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
    pthread_lock *lock;
    int status, error = 0;

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

    lock = (pthread_lock *) malloc(sizeof(pthread_lock));
    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) {
            free((void *)lock);
            lock = 0;
        }
    }

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

422
void
423
PyThread_free_lock(PyThread_type_lock lock)
424
{
425 426
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
427

428
    dprintf(("PyThread_free_lock(%p) called\n", lock));
429

430 431
    status = pthread_mutex_destroy( &thelock->mut );
    CHECK_STATUS("pthread_mutex_destroy");
432

433 434
    status = pthread_cond_destroy( &thelock->lock_released );
    CHECK_STATUS("pthread_cond_destroy");
435

436
    free((void *)thelock);
437 438
}

439 440 441
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
                            int intr_flag)
442
{
443
    PyLockStatus success;
444 445 446
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;

447 448
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
449 450 451 452

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

453 454 455 456 457
    if (thelock->locked == 0) {
        success = PY_LOCK_ACQUIRED;
    } else if (microseconds == 0) {
        success = PY_LOCK_FAILURE;
    } else {
458 459 460 461 462 463 464
        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 */
465 466
        success = PY_LOCK_FAILURE;
        while (success == PY_LOCK_FAILURE) {
467 468 469 470 471 472 473 474 475 476 477 478 479 480
            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");
            }
481 482 483 484 485 486 487 488 489 490 491 492

            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;
            }
493 494
        }
    }
495
    if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
496 497 498
    status = pthread_mutex_unlock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_unlock[1]");

499 500 501
    if (error) success = PY_LOCK_FAILURE;
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
502
    return success;
503 504
}

505
void
506
PyThread_release_lock(PyThread_type_lock lock)
507
{
508 509
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
510

511
    dprintf(("PyThread_release_lock(%p) called\n", lock));
512

513 514
    status = pthread_mutex_lock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_lock[3]");
515

516
    thelock->locked = 0;
517

518 519
    status = pthread_mutex_unlock( &thelock->mut );
    CHECK_STATUS("pthread_mutex_unlock[3]");
520

521 522 523
    /* wake up someone (anyone, if any) waiting on the lock */
    status = pthread_cond_signal( &thelock->lock_released );
    CHECK_STATUS("pthread_cond_signal");
524
}
525 526

#endif /* USE_SEMAPHORES */
527

528 529 530 531 532 533
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
    return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);
}

534 535 536 537 538 539 540 541
/* 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)
542 543 544
    pthread_attr_t attrs;
    size_t tss_min;
    int rc = 0;
545 546
#endif

547 548 549 550 551
    /* set to default */
    if (size == 0) {
        _pythread_stacksize = 0;
        return 0;
    }
552 553 554

#if defined(THREAD_STACK_SIZE)
#if defined(PTHREAD_STACK_MIN)
555 556
    tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
                                                   : THREAD_STACK_MIN;
557
#else
558
    tss_min = THREAD_STACK_MIN;
559
#endif
560 561 562 563 564 565 566 567 568 569 570 571
    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;
572
#else
573
    return -2;
574 575 576
#endif
}

577
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620

#define Py_HAVE_NATIVE_TLS

int
PyThread_create_key(void)
{
    pthread_key_t key;
    int fail = pthread_key_create(&key, NULL);
    return fail ? -1 : key;
}

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;
    void *oldValue = pthread_getspecific(key);
    if (oldValue != NULL)
        return 0;
    fail = pthread_setspecific(key, value);
    return fail ? -1 : 0;
}

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

void
PyThread_ReInitTLS(void)
{}