thread_pthread.h 21 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  /* 32 KiB */
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
#define CHECK_STATUS_PTHREAD(name)  if (status != 0) { fprintf(stderr, \
    "%s: %s\n", name, strerror(status)); error = 1; }
148

149 150 151
/*
 * Initialization.
 */
152 153
static void
PyThread__init_thread(void)
154
{
155
#if defined(_AIX) && defined(__GNUC__)
156
    extern void pthread_init(void);
157
    pthread_init();
158
#endif
159 160 161 162 163
}

/*
 * Thread support.
 */
164 165


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

178 179 180
    dprintf(("PyThread_start_new_thread called\n"));
    if (!initialized)
        PyThread_init_thread();
181

182
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
183
    if (pthread_attr_init(&attrs) != 0)
184
        return PYTHREAD_INVALID_THREAD_ID;
185
#endif
186
#if defined(THREAD_STACK_SIZE)
187 188 189
    PyThreadState *tstate = PyThreadState_GET();
    size_t stacksize = tstate ? tstate->interp->pythread_stacksize : 0;
    tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE;
190 191 192
    if (tss != 0) {
        if (pthread_attr_setstacksize(&attrs, tss) != 0) {
            pthread_attr_destroy(&attrs);
193
            return PYTHREAD_INVALID_THREAD_ID;
194 195
        }
    }
196
#endif
197
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
198
    pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
199
#endif
200

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

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

217
    pthread_detach(th);
218

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

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

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

251 252 253 254 255 256
#ifdef USE_SEMAPHORES

/*
 * Lock support.
 */

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

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

267
    lock = (sem_t *)PyMem_RawMalloc(sizeof(sem_t));
268

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

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

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

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

289
    (void) error; /* silence unused-but-set-variable warning */
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
    PyMem_RawFree((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
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
    struct timespec ts;
321
    _PyTime_t deadline = 0;
322

323
    (void) error; /* silence unused-but-set-variable warning */
324 325
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
326

327 328 329 330 331
    if (microseconds > PY_TIMEOUT_MAX) {
        Py_FatalError("Timeout larger than PY_TIMEOUT_MAX");
    }

    if (microseconds > 0) {
332
        MICROSECONDS_TO_TIMESPEC(microseconds, ts);
333 334 335 336 337 338 339 340 341 342 343

        if (!intr_flag) {
            /* cannot overflow thanks to (microseconds > PY_TIMEOUT_MAX)
               check done above */
            _PyTime_t timeout = _PyTime_FromNanoseconds(microseconds * 1000);
            deadline = _PyTime_GetMonotonicClock() + timeout;
        }
    }

    while (1) {
        if (microseconds > 0) {
344
            status = fix_status(sem_timedwait(thelock, &ts));
345 346
        }
        else if (microseconds == 0) {
347
            status = fix_status(sem_trywait(thelock));
348 349
        }
        else {
350
            status = fix_status(sem_wait(thelock));
351 352
        }

353 354
        /* Retry if interrupted by a signal, unless the caller wants to be
           notified.  */
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
        if (intr_flag || status != EINTR) {
            break;
        }

        if (microseconds > 0) {
            /* wait interrupted by a signal (EINTR): recompute the timeout */
            _PyTime_t dt = deadline - _PyTime_GetMonotonicClock();
            if (dt < 0) {
                status = ETIMEDOUT;
                break;
            }
            else if (dt > 0) {
                _PyTime_t realtime_deadline = _PyTime_GetSystemClock() + dt;
                if (_PyTime_AsTimespec(realtime_deadline, &ts) < 0) {
                    /* Cannot occur thanks to (microseconds > PY_TIMEOUT_MAX)
                       check done above */
                    Py_UNREACHABLE();
                }
                /* no need to update microseconds value, the code only care
                   if (microseconds > 0 or (microseconds == 0). */
            }
            else {
                microseconds = 0;
            }
        }
    }
381 382 383 384 385 386 387 388 389 390 391 392 393 394

    /* 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");
        }
395 396
    }

397 398 399 400 401 402 403
    if (status == 0) {
        success = PY_LOCK_ACQUIRED;
    } else if (intr_flag && status == EINTR) {
        success = PY_LOCK_INTR;
    } else {
        success = PY_LOCK_FAILURE;
    }
404

405 406
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
407
    return success;
408 409
}

410
void
411 412
PyThread_release_lock(PyThread_type_lock lock)
{
413 414
    sem_t *thelock = (sem_t *)lock;
    int status, error = 0;
415

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

419 420
    status = sem_post(thelock);
    CHECK_STATUS("sem_post");
421 422 423 424
}

#else /* USE_SEMAPHORES */

425 426 427
/*
 * Lock support.
 */
428
PyThread_type_lock
429
PyThread_allocate_lock(void)
430
{
431 432 433 434 435 436 437
    pthread_lock *lock;
    int status, error = 0;

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

438
    lock = (pthread_lock *) PyMem_RawMalloc(sizeof(pthread_lock));
439 440 441 442 443 444
    if (lock) {
        memset((void *)lock, '\0', sizeof(pthread_lock));
        lock->locked = 0;

        status = pthread_mutex_init(&lock->mut,
                                    pthread_mutexattr_default);
445
        CHECK_STATUS_PTHREAD("pthread_mutex_init");
446 447 448 449 450 451 452 453 454
        /* 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);
455
        CHECK_STATUS_PTHREAD("pthread_cond_init");
456 457

        if (error) {
458
            PyMem_RawFree((void *)lock);
459 460 461 462 463 464
            lock = 0;
        }
    }

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

467
void
468
PyThread_free_lock(PyThread_type_lock lock)
469
{
470 471
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
472

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

476 477 478
    /* some pthread-like implementations tie the mutex to the cond
     * and must have the cond destroyed first.
     */
479
    status = pthread_cond_destroy( &thelock->lock_released );
480
    CHECK_STATUS_PTHREAD("pthread_cond_destroy");
481

482
    status = pthread_mutex_destroy( &thelock->mut );
483
    CHECK_STATUS_PTHREAD("pthread_mutex_destroy");
484

485
    PyMem_RawFree((void *)thelock);
486 487
}

488 489 490
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
                            int intr_flag)
491
{
492
    PyLockStatus success = PY_LOCK_FAILURE;
493 494 495
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;

496 497
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
             lock, microseconds, intr_flag));
498

499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    if (microseconds == 0) {
        status = pthread_mutex_trylock( &thelock->mut );
        if (status != EBUSY)
            CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]");
    }
    else {
        status = pthread_mutex_lock( &thelock->mut );
        CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
    }
    if (status == 0) {
        if (thelock->locked == 0) {
            success = PY_LOCK_ACQUIRED;
        }
        else if (microseconds != 0) {
            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 */
            while (success == PY_LOCK_FAILURE) {
                if (microseconds > 0) {
                    status = pthread_cond_timedwait(
                        &thelock->lock_released,
                        &thelock->mut, &ts);
                    if (status == ETIMEDOUT)
                        break;
                    CHECK_STATUS_PTHREAD("pthread_cond_timed_wait");
                }
                else {
                    status = pthread_cond_wait(
                        &thelock->lock_released,
                        &thelock->mut);
                    CHECK_STATUS_PTHREAD("pthread_cond_wait");
                }

                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;
541
                    break;
542 543 544 545
                }
                else if (status == 0 && !thelock->locked) {
                    success = PY_LOCK_ACQUIRED;
                }
546
            }
547
        }
548 549 550
        if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
        status = pthread_mutex_unlock( &thelock->mut );
        CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");
551 552
    }

553 554 555
    if (error) success = PY_LOCK_FAILURE;
    dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
             lock, microseconds, intr_flag, success));
556
    return success;
557 558
}

559
void
560
PyThread_release_lock(PyThread_type_lock lock)
561
{
562 563
    pthread_lock *thelock = (pthread_lock *)lock;
    int status, error = 0;
564

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

568
    status = pthread_mutex_lock( &thelock->mut );
569
    CHECK_STATUS_PTHREAD("pthread_mutex_lock[3]");
570

571
    thelock->locked = 0;
572

573 574
    /* wake up someone (anyone, if any) waiting on the lock */
    status = pthread_cond_signal( &thelock->lock_released );
575
    CHECK_STATUS_PTHREAD("pthread_cond_signal");
576 577

    status = pthread_mutex_unlock( &thelock->mut );
578
    CHECK_STATUS_PTHREAD("pthread_mutex_unlock[3]");
579
}
580 581

#endif /* USE_SEMAPHORES */
582

583 584 585 586 587 588
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
    return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);
}

589 590 591 592 593 594 595 596
/* 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)
597 598 599
    pthread_attr_t attrs;
    size_t tss_min;
    int rc = 0;
600 601
#endif

602 603
    /* set to default */
    if (size == 0) {
604
        PyThreadState_GET()->interp->pythread_stacksize = 0;
605 606
        return 0;
    }
607 608 609

#if defined(THREAD_STACK_SIZE)
#if defined(PTHREAD_STACK_MIN)
610 611
    tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
                                                   : THREAD_STACK_MIN;
612
#else
613
    tss_min = THREAD_STACK_MIN;
614
#endif
615 616 617 618 619 620
    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) {
621
                PyThreadState_GET()->interp->pythread_stacksize = size;
622 623 624 625 626
                return 0;
            }
        }
    }
    return -1;
627
#else
628
    return -2;
629 630 631
#endif
}

632
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
633 634


635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
/* Thread Local Storage (TLS) API

   This API is DEPRECATED since Python 3.7.  See PEP 539 for details.
*/

/* Issue #25658: On platforms where native TLS key is defined in a way that
   cannot be safely cast to int, PyThread_create_key returns immediately a
   failure status and other TLS functions all are no-ops.  This indicates
   clearly that the old API is not supported on platforms where it cannot be
   used reliably, and that no effort will be made to add such support.

   Note: PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT will be unnecessary after
   removing this API.
*/

650 651 652
int
PyThread_create_key(void)
{
653
#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
654 655
    pthread_key_t key;
    int fail = pthread_key_create(&key, NULL);
656 657 658 659 660 661 662 663 664
    if (fail)
        return -1;
    if (key > INT_MAX) {
        /* Issue #22206: handle integer overflow */
        pthread_key_delete(key);
        errno = ENOMEM;
        return -1;
    }
    return (int)key;
665 666 667
#else
    return -1;  /* never return valid key value. */
#endif
668 669 670 671 672
}

void
PyThread_delete_key(int key)
{
673
#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
674
    pthread_key_delete(key);
675
#endif
676 677 678 679 680
}

void
PyThread_delete_key_value(int key)
{
681
#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
682
    pthread_setspecific(key, NULL);
683
#endif
684 685 686 687 688
}

int
PyThread_set_key_value(int key, void *value)
{
689 690
#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
    int fail = pthread_setspecific(key, value);
691
    return fail ? -1 : 0;
692 693 694
#else
    return -1;
#endif
695 696 697 698 699
}

void *
PyThread_get_key_value(int key)
{
700
#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
701
    return pthread_getspecific(key);
702 703 704
#else
    return NULL;
#endif
705 706
}

707

708 709
void
PyThread_ReInitTLS(void)
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
{
}


/* Thread Specific Storage (TSS) API

   Platform-specific components of TSS API implementation.
*/

int
PyThread_tss_create(Py_tss_t *key)
{
    assert(key != NULL);
    /* If the key has been created, function is silently skipped. */
    if (key->_is_initialized) {
        return 0;
    }

    int fail = pthread_key_create(&(key->_key), NULL);
    if (fail) {
        return -1;
    }
    key->_is_initialized = 1;
    return 0;
}

void
PyThread_tss_delete(Py_tss_t *key)
{
    assert(key != NULL);
    /* If the key has not been created, function is silently skipped. */
    if (!key->_is_initialized) {
        return;
    }

    pthread_key_delete(key->_key);
    /* pthread has not provided the defined invalid value for the key. */
    key->_is_initialized = 0;
}

int
PyThread_tss_set(Py_tss_t *key, void *value)
{
    assert(key != NULL);
    int fail = pthread_setspecific(key->_key, value);
    return fail ? -1 : 0;
}

void *
PyThread_tss_get(Py_tss_t *key)
{
    assert(key != NULL);
    return pthread_getspecific(key->_key);
}