diff -r 9e5bc3d38de8 Include/pythread.h --- a/Include/pythread.h Mon Dec 05 16:59:22 2016 +1000 +++ b/Include/pythread.h Mon Dec 05 18:34:43 2016 +0900 @@ -25,8 +25,8 @@ PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void); PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock); PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int); -#define WAIT_LOCK 1 -#define NOWAIT_LOCK 0 +#define WAIT_LOCK 1 +#define NOWAIT_LOCK 0 /* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting on a lock (see PyThread_acquire_lock_timed() below). @@ -71,12 +71,39 @@ PyAPI_FUNC(PyObject*) PyThread_GetInfo(void); -/* Thread Local Storage (TLS) API */ -PyAPI_FUNC(int) PyThread_create_key(void); -PyAPI_FUNC(void) PyThread_delete_key(int); -PyAPI_FUNC(int) PyThread_set_key_value(int, void *); -PyAPI_FUNC(void *) PyThread_get_key_value(int); -PyAPI_FUNC(void) PyThread_delete_key_value(int key); +/* Thread Local Storage (TLS) API + TLS API is DEPRECATED. Use Thread Specific Storage API. + + Because the platforms that native TLS key type is not integer exist + (e.g. CloudABI, Cygwin). If those platforms go to support TLS API as is, + CPython perform will go down or implementation will be complicated. + Therefore New TSS API is implemented to use wrapped native TLS key type + by typedef. +*/ +PyAPI_FUNC(int) PyThread_create_key(void) Py_DEPRECATED(3.7); +PyAPI_FUNC(void) PyThread_delete_key(int key) Py_DEPRECATED(3.7); +PyAPI_FUNC(int) PyThread_set_key_value(int key, void *val) Py_DEPRECATED(3.7); +PyAPI_FUNC(void *) PyThread_get_key_value(int key) Py_DEPRECATED(3.7); +PyAPI_FUNC(void) PyThread_delete_key_value(int key) Py_DEPRECATED(3.7); + +/* Thread Specific Storage (TSS) API + + Based on C11 threads, but destructor doesn't support because you need to + manage memory by yourself. And the delete value function is maintained + for the implementation by CPython self. +*/ +#if defined(_POSIX_THREADS) +typedef pthread_key_t Py_tss_t; +#elif defined(NT_THREADS) +typedef DWORD Py_tss_t; +#else /* implementation by CPython self */ +typedef int Py_tss_t; +#endif +PyAPI_FUNC(int) PyThread_tss_create(Py_tss_t *out_key); +PyAPI_FUNC(void) PyThread_tss_delete(Py_tss_t key); +PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t key, void *value); +PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t key); +PyAPI_FUNC(void) PyThread_tss_delete_value(Py_tss_t key); /* Cleanup after a fork */ PyAPI_FUNC(void) PyThread_ReInitTLS(void); diff -r 9e5bc3d38de8 Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c Mon Dec 05 16:59:22 2016 +1000 +++ b/Modules/_tracemalloc.c Mon Dec 05 18:34:43 2016 +0900 @@ -4,6 +4,8 @@ #include "pythread.h" #include "osdefs.h" +#include + /* Trace memory blocks allocated by PyMem_RawMalloc() */ #define TRACE_RAW_MALLOC @@ -165,7 +167,8 @@ # error "need native thread local storage (TLS)" #endif -static int tracemalloc_reentrant_key = -1; +static Py_tss_t tracemalloc_reentrant_key; +static bool key_used = false; /* Any non-NULL pointer can be used */ #define REENTRANT Py_True @@ -175,8 +178,8 @@ { void *ptr; - assert(tracemalloc_reentrant_key != -1); - ptr = PyThread_get_key_value(tracemalloc_reentrant_key); + assert(key_used); + ptr = PyThread_tss_get(tracemalloc_reentrant_key); if (ptr != NULL) { assert(ptr == REENTRANT); return 1; @@ -189,15 +192,15 @@ set_reentrant(int reentrant) { assert(reentrant == 0 || reentrant == 1); - assert(tracemalloc_reentrant_key != -1); + assert(key_used); if (reentrant) { assert(!get_reentrant()); - PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT); + PyThread_tss_set(tracemalloc_reentrant_key, REENTRANT); } else { assert(get_reentrant()); - PyThread_set_key_value(tracemalloc_reentrant_key, NULL); + PyThread_tss_set(tracemalloc_reentrant_key, NULL); } } @@ -987,8 +990,7 @@ PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); #ifdef REENTRANT_THREADLOCAL - tracemalloc_reentrant_key = PyThread_create_key(); - if (tracemalloc_reentrant_key == -1) { + if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) { #ifdef MS_WINDOWS PyErr_SetFromWindowsErr(0); #else @@ -996,6 +998,7 @@ #endif return -1; } + key_used = true; #endif #if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC) @@ -1073,8 +1076,8 @@ #endif #ifdef REENTRANT_THREADLOCAL - PyThread_delete_key(tracemalloc_reentrant_key); - tracemalloc_reentrant_key = -1; + PyThread_tss_delete(tracemalloc_reentrant_key); + key_used = false; #endif Py_XDECREF(unknown_filename); diff -r 9e5bc3d38de8 Python/pystate.c --- a/Python/pystate.c Mon Dec 05 16:59:22 2016 +1000 +++ b/Python/pystate.c Mon Dec 05 18:34:43 2016 +0900 @@ -3,6 +3,8 @@ #include "Python.h" +#include + #define GET_TSTATE() \ ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) #define SET_TSTATE(value) \ @@ -47,7 +49,8 @@ GILState implementation */ static PyInterpreterState *autoInterpreterState = NULL; -static int autoTLSkey = -1; +static Py_tss_t autoTLSkey; +static bool keyUsed = false; #else #define HEAD_INIT() /* Nothing */ #define HEAD_LOCK() /* Nothing */ @@ -444,8 +447,8 @@ if (tstate == GET_TSTATE()) Py_FatalError("PyThreadState_Delete: tstate is still current"); #ifdef WITH_THREAD - if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); + if (autoInterpreterState && PyThread_tss_get(autoTLSkey) == tstate) + PyThread_tss_delete_value(autoTLSkey); #endif /* WITH_THREAD */ tstate_delete_common(tstate); } @@ -460,8 +463,8 @@ Py_FatalError( "PyThreadState_DeleteCurrent: no current tstate"); tstate_delete_common(tstate); - if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); + if (autoInterpreterState && PyThread_tss_get(autoTLSkey) == tstate) + PyThread_tss_delete_value(autoTLSkey); SET_TSTATE(NULL); PyEval_ReleaseLock(); } @@ -712,11 +715,11 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { assert(i && t); /* must init with valid states */ - autoTLSkey = PyThread_create_key(); - if (autoTLSkey == -1) + if (PyThread_tss_create(&autoTLSkey) != 0) Py_FatalError("Could not allocate TLS entry"); + keyUsed = true; autoInterpreterState = i; - assert(PyThread_get_key_value(autoTLSkey) == NULL); + assert(PyThread_tss_get(autoTLSkey) == NULL); assert(t->gilstate_counter == 0); _PyGILState_NoteThreadState(t); @@ -731,8 +734,8 @@ void _PyGILState_Fini(void) { - PyThread_delete_key(autoTLSkey); - autoTLSkey = -1; + PyThread_tss_delete(autoTLSkey); + keyUsed = false; autoInterpreterState = NULL; } @@ -744,13 +747,13 @@ _PyGILState_Reinit(void) { PyThreadState *tstate = PyGILState_GetThisThreadState(); - PyThread_delete_key(autoTLSkey); - if ((autoTLSkey = PyThread_create_key()) == -1) + PyThread_tss_delete(autoTLSkey); + if (PyThread_tss_create(&autoTLSkey) != 0) Py_FatalError("Could not allocate TLS entry"); /* If the thread had an associated auto thread state, reassociate it with * the new key. */ - if (tstate && PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + if (tstate && PyThread_tss_set(autoTLSkey, (void *)tstate) != 0) Py_FatalError("Couldn't create autoTLSkey mapping"); } @@ -780,8 +783,8 @@ The first thread state created for that given OS level thread will "win", which seems reasonable behaviour. */ - if (PyThread_get_key_value(autoTLSkey) == NULL) { - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + if (PyThread_tss_get(autoTLSkey) == NULL) { + if (PyThread_tss_set(autoTLSkey, (void *)tstate) != 0) Py_FatalError("Couldn't create autoTLSkey mapping"); } @@ -795,7 +798,7 @@ { if (autoInterpreterState == NULL) return NULL; - return (PyThreadState *)PyThread_get_key_value(autoTLSkey); + return (PyThreadState *)PyThread_tss_get(autoTLSkey); } int @@ -806,7 +809,7 @@ if (!_PyGILState_check_enabled) return 1; - if (autoTLSkey == -1) + if (!keyUsed) return 1; tstate = GET_TSTATE(); @@ -827,7 +830,7 @@ called Py_Initialize() and usually PyEval_InitThreads(). */ assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ - tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); + tcur = (PyThreadState *)PyThread_tss_get(autoTLSkey); if (tcur == NULL) { /* At startup, Python has no concrete GIL. If PyGILState_Ensure() is called from a new thread for the first time, we need the create the @@ -859,8 +862,7 @@ void PyGILState_Release(PyGILState_STATE oldstate) { - PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( - autoTLSkey); + PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(autoTLSkey); if (tcur == NULL) Py_FatalError("auto-releasing thread-state, " "but no thread-state for this thread"); diff -r 9e5bc3d38de8 Python/thread.c --- a/Python/thread.c Mon Dec 05 16:59:22 2016 +1000 +++ b/Python/thread.c Mon Dec 05 18:34:43 2016 +0900 @@ -130,20 +130,20 @@ /* ------------------------------------------------------------------------ Per-thread data ("key") support. -Use PyThread_create_key() to create a new key. This is typically shared +Use PyThread_tss_create() to create a new key. This is typically shared across threads. -Use PyThread_set_key_value(thekey, value) to associate void* value with +Use PyThread_tss_set(thekey, value) to associate void* value with thekey in the current thread. Each thread has a distinct mapping of thekey to a void* value. Caution: if the current thread already has a mapping for thekey, value is ignored. -Use PyThread_get_key_value(thekey) to retrieve the void* value associated +Use PyThread_tss_get(thekey) to retrieve the void* value associated with thekey in the current thread. This returns NULL if no value is associated with thekey in the current thread. -Use PyThread_delete_key_value(thekey) to forget the current thread's associated -value for thekey. PyThread_delete_key(thekey) forgets the values associated +Use PyThread_tss_delete_value(thekey) to forget the current thread's associated +value for thekey. PyThread_tss_delete(thekey) forgets the values associated with thekey across *all* threads. While some of these functions have error-return values, none set any @@ -155,12 +155,12 @@ them either. The GIL does not need to be held when calling these functions; they supply -their own locking. This isn't true of PyThread_create_key(), though (see +their own locking. This isn't true of PyThread_tss_create(), though (see next paragraph). -There's a hidden assumption that PyThread_create_key() will be called before +There's a hidden assumption that PyThread_tss_create() will be called before any of the other functions are called. There's also a hidden assumption -that calls to PyThread_create_key() are serialized externally. +that calls to PyThread_tss_create() are serialized externally. ------------------------------------------------------------------------ */ /* A singly-linked list of struct key objects remembers all the key->value @@ -181,7 +181,7 @@ static struct key *keyhead = NULL; static PyThread_type_lock keymutex = NULL; -static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ +static int nkeys = 0; /* PyThread_tss_create() hands out nkeys+1 next */ /* Internal helper. * If the current thread has a mapping for key, the appropriate struct key* @@ -200,7 +200,7 @@ * another thread to mutate the list, via key deletion, concurrent with * find_key() crawling over the list. Hilarity ensued. For example, when * the for-loop here does "p = p->next", p could end up pointing at a - * record that PyThread_delete_key_value() was concurrently free()'ing. + * record that PyThread_tss_delete_value() was concurrently free()'ing. * That could lead to anything, from failing to find a key that exists, to * segfaults. Now we lock the whole routine. */ @@ -247,24 +247,66 @@ return p; } -/* Return a new key. This must be called before any other functions in + +/* Thread Local Storage (TLS) API, *DEPRECATED* since 3.7 + + TLS API is changed to call New TSS API. +*/ + +int +PyThread_create_key(void) +{ + int key; + PyThread_tss_create(&key); + return key; +} + +void +PyThread_delete_key(int key) +{ + PyThread_tss_delete(key); +} + +int +PyThread_set_key_value(int key, void *value) +{ + return PyThread_tss_set(key, value); +} + +void * +PyThread_get_key_value(int key) +{ + return PyThread_tss_get(key); +} + +void +PyThread_delete_key_value(int key) +{ + PyThread_tss_delete_value(key); +} + + +/* Thread Specific Storage (TSS) API */ + +/* Assign a new key. This must be called before any other functions in * this family, and callers must arrange to serialize calls to this * function. No violations are detected. */ int -PyThread_create_key(void) +PyThread_tss_create(Py_tss_t *out_key) { /* All parts of this function are wrong if it's called by multiple * threads simultaneously. */ if (keymutex == NULL) keymutex = PyThread_allocate_lock(); - return ++nkeys; + *out_key = ++nkeys; + return 0; } /* Forget the associations for key across *all* threads. */ void -PyThread_delete_key(int key) +PyThread_tss_delete(Py_tss_t key) { struct key *p, **q; @@ -283,7 +325,7 @@ } int -PyThread_set_key_value(int key, void *value) +PyThread_tss_set(Py_tss_t key, void *value) { struct key *p; @@ -298,7 +340,7 @@ * if the current thread doesn't have an association for key. */ void * -PyThread_get_key_value(int key) +PyThread_tss_get(Py_tss_t key) { struct key *p = find_key(0, key, NULL); @@ -310,7 +352,7 @@ /* Forget the current thread's association for key, if any. */ void -PyThread_delete_key_value(int key) +PyThread_tss_delete_value(Py_tss_t key) { long id = PyThread_get_thread_ident(); struct key *p, **q; @@ -330,6 +372,7 @@ PyThread_release_lock(keymutex); } + /* Forget everything not associated with the current thread id. * This function is called from PyOS_AfterFork(). It is necessary * because other thread ids which were in use at the time of the fork diff -r 9e5bc3d38de8 Python/thread_foobar.h --- a/Python/thread_foobar.h Mon Dec 05 16:59:22 2016 +1000 +++ b/Python/thread_foobar.h Mon Dec 05 18:34:43 2016 +0900 @@ -71,7 +71,7 @@ dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", lock, microseconds, intr_flag)); dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", - lock, microseconds, intr_flag, success)); + lock, microseconds, intr_flag, success)); return success; } @@ -85,6 +85,9 @@ #define Py_HAVE_NATIVE_TLS #ifdef Py_HAVE_NATIVE_TLS + +/* Thread Local Storage (TLS) API, *DEPRECATED* since 3.7 */ + int PyThread_create_key(void) { @@ -123,6 +126,53 @@ } + +/* Thread Specific Storage (TSS) API */ + +int +PyThread_tss_create(Py_tss_t *out_key) +{ + Py_tss_t new_key; + + /* A failure in this case returns -1 */ + if (!new_key) + return -1; + *out_key = new_key; + return 0; +} + +void +PyThread_tss_delete(Py_tss_t key) +{ + +} + +int +PyThread_tss_set(Py_tss_t key, void *value) +{ + int ok; + + /* A failure in this case returns -1 */ + if (!ok) + return -1; + return 0; +} + +void * +PyThread_tss_get(Py_tss_t key) +{ + void *result; + + return result; +} + +void +PyThread_tss_delete_value(Py_tss_t key) +{ + +} + + void PyThread_ReInitTLS(void) { diff -r 9e5bc3d38de8 Python/thread_nt.h --- a/Python/thread_nt.h Mon Dec 05 16:59:22 2016 +1000 +++ b/Python/thread_nt.h Mon Dec 05 18:34:43 2016 +0900 @@ -352,11 +352,17 @@ #define Py_HAVE_NATIVE_TLS #ifdef Py_HAVE_NATIVE_TLS + +/* Thread Local Storage (TLS) API, *DEPRECATED* since 3.7 + + TLS API is changed to call New TSS API. +*/ + int PyThread_create_key(void) { - DWORD result= TlsAlloc(); - if (result == TLS_OUT_OF_INDEXES) + DWORD result; + if (PyThread_tss_create(&result) != 0) return -1; return (int)result; } @@ -364,23 +370,56 @@ void PyThread_delete_key(int key) { - TlsFree(key); + PyThread_tss_delete(key); } int PyThread_set_key_value(int key, void *value) { - BOOL ok; - - ok = TlsSetValue(key, value); - if (!ok) - return -1; - return 0; + return PyThread_tss_set(key, value); } void * PyThread_get_key_value(int key) { + return PyThread_tss_get(key); +} + +void +PyThread_delete_key_value(int key) +{ + PyThread_tss_delete_value(key); +} + + +/* Thread Specific Storage (TSS) API */ + +int +PyThread_tss_create(Py_tss_t *out_key) +{ + DWORD result = TlsAlloc(); + if (result == TLS_OUT_OF_INDEXES) + return -1; + *out_key = result; + return 0; +} + +void +PyThread_tss_delete(Py_tss_t key) +{ + TlsFree(key); +} + +int +PyThread_tss_set(Py_tss_t key, void *value) +{ + BOOL ok = TlsSetValue(key, value); + return ok ? 0 : -1; +} + +void * +PyThread_tss_get(Py_tss_t key) +{ /* because TLS is used in the Py_END_ALLOW_THREAD macro, * it is necessary to preserve the windows error state, because * it is assumed to be preserved across the call to the macro. @@ -394,7 +433,7 @@ } void -PyThread_delete_key_value(int key) +PyThread_tss_delete_value(Py_tss_t key) { /* NULL is used as "key missing", and it is also the default * given by TlsGetValue() if nothing has been set yet. @@ -402,6 +441,7 @@ TlsSetValue(key, NULL); } + /* reinitialization of TLS is not necessary after fork when using * the native TLS functions. And forking isn't supported on Windows either. */ diff -r 9e5bc3d38de8 Python/thread_pthread.h --- a/Python/thread_pthread.h Mon Dec 05 16:59:22 2016 +1000 +++ b/Python/thread_pthread.h Mon Dec 05 18:34:43 2016 +0900 @@ -603,9 +603,16 @@ #define Py_HAVE_NATIVE_TLS +/* Thread Local Storage (TLS) API, *DEPRECATED* since 3.7 + + Issue #25658: POSIX doesn't require that pthread_key_t is integer. + If key type isn't integer, TLS functions always do nothing or fail. +*/ + int PyThread_create_key(void) { +#ifdef PTHREAD_KEY_T_IS_INTEGER pthread_key_t key; int fail = pthread_key_create(&key, NULL); if (fail) @@ -617,34 +624,85 @@ return -1; } return (int)key; +#else + return -1; +#endif } void PyThread_delete_key(int key) { +#ifdef PTHREAD_KEY_T_IS_INTEGER pthread_key_delete(key); +#endif } void PyThread_delete_key_value(int key) { +#ifdef PTHREAD_KEY_T_IS_INTEGER pthread_setspecific(key, NULL); +#endif } int PyThread_set_key_value(int key, void *value) { +#ifdef PTHREAD_KEY_T_IS_INTEGER int fail; fail = pthread_setspecific(key, value); return fail ? -1 : 0; +#else + return -1; +#endif } void * PyThread_get_key_value(int key) { +#ifdef PTHREAD_KEY_T_IS_INTEGER + return pthread_getspecific(key); +#else + return NULL; +#endif +} + + +/* Thread Specific Storage (TSS) API */ + +int +PyThread_tss_create(Py_tss_t *out_key) +{ + int fail = pthread_key_create(out_key, NULL); + return fail ? -1 : 0; +} + +void +PyThread_tss_delete(Py_tss_t key) +{ + pthread_key_delete(key); +} + +int +PyThread_tss_set(Py_tss_t key, void *value) +{ + int fail = pthread_setspecific(key, value); + return fail ? -1 : 0; +} + +void * +PyThread_tss_get(Py_tss_t key) +{ return pthread_getspecific(key); } void +PyThread_tss_delete_value(Py_tss_t key) +{ + pthread_setspecific(key, NULL); +} + + +void PyThread_ReInitTLS(void) {} diff -r 9e5bc3d38de8 configure --- a/configure Mon Dec 05 16:59:22 2016 +1000 +++ b/configure Mon Dec 05 18:34:43 2016 +0900 @@ -9001,6 +9001,35 @@ fi + +# Issue #25658: POSIX doesn't require that pthread_key_t is integer. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_key_t is integer" >&5 +$as_echo_n "checking whether pthread_key_t is integer... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_key_t k; k * 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_pthread_key_t_is_integer=yes +else + ac_pthread_key_t_is_integer=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pthread_key_t_is_integer" >&5 +$as_echo "$ac_pthread_key_t_is_integer" >&6; } +if test "$ac_pthread_key_t_is_integer" = yes ; then + +$as_echo "#define PTHREAD_KEY_T_IS_INTEGER 1" >>confdefs.h + +fi CC="$ac_save_cc" diff -r 9e5bc3d38de8 configure.ac --- a/configure.ac Mon Dec 05 16:59:22 2016 +1000 +++ b/configure.ac Mon Dec 05 18:34:43 2016 +0900 @@ -2268,6 +2268,19 @@ #endif ]) fi + +# Issue #25658: POSIX doesn't require that pthread_key_t is integer. +AC_MSG_CHECKING(whether pthread_key_t is integer) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], [[pthread_key_t k; k * 1;]])], + [ac_pthread_key_t_is_integer=yes], + [ac_pthread_key_t_is_integer=no] +) +AC_MSG_RESULT($ac_pthread_key_t_is_integer) +if test "$ac_pthread_key_t_is_integer" = yes ; then + AC_DEFINE(PTHREAD_KEY_T_IS_INTEGER, 1, + [Define if pthread_key_t is integer.]) +fi CC="$ac_save_cc" AC_SUBST(OTHER_LIBTOOL_OPT) diff -r 9e5bc3d38de8 pyconfig.h.in --- a/pyconfig.h.in Mon Dec 05 16:59:22 2016 +1000 +++ b/pyconfig.h.in Mon Dec 05 18:34:43 2016 +0900 @@ -1238,6 +1238,9 @@ /* Define if POSIX semaphores aren't enabled on your system */ #undef POSIX_SEMAPHORES_NOT_ENABLED +/* Define if pthread_key_t is integer. */ +#undef PTHREAD_KEY_T_IS_INTEGER + /* Defined if PTHREAD_SCOPE_SYSTEM supported. */ #undef PTHREAD_SYSTEM_SCHED_SUPPORTED