gh-140544: Always assume that thread locals are available (GH-140690)

Python has required thread local support since 3.12 (see GH-103324). By assuming that thread locals are always supported, we can improve the performance of third-party extensions by allowing them to access the attached thread and interpreter states directly.
This commit is contained in:
Peter Bierma 2025-10-28 09:07:19 -04:00 committed by GitHub
parent 88ad41fa34
commit 2cefa70eb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 12 additions and 34 deletions

View file

@ -509,23 +509,18 @@ extern "C" {
#endif #endif
#ifdef WITH_THREAD #ifdef WITH_THREAD
# ifdef Py_BUILD_CORE // HAVE_THREAD_LOCAL is just defined here for compatibility's sake
# ifdef HAVE_THREAD_LOCAL # define HAVE_THREAD_LOCAL 1
# error "HAVE_THREAD_LOCAL is already defined" # ifdef thread_local
# endif # define _Py_thread_local thread_local
# define HAVE_THREAD_LOCAL 1 # elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
# ifdef thread_local # define _Py_thread_local _Thread_local
# define _Py_thread_local thread_local # elif defined(_MSC_VER) /* AKA NT_THREADS */
# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) # define _Py_thread_local __declspec(thread)
# define _Py_thread_local _Thread_local # elif defined(__GNUC__) /* includes clang */
# elif defined(_MSC_VER) /* AKA NT_THREADS */ # define _Py_thread_local __thread
# define _Py_thread_local __declspec(thread) # else
# elif defined(__GNUC__) /* includes clang */ # error "no supported thread-local variable storage classifier"
# define _Py_thread_local __thread
# else
// fall back to the PyThread_tss_*() API, or ignore.
# undef HAVE_THREAD_LOCAL
# endif
# endif # endif
#endif #endif

View file

@ -782,18 +782,13 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
substitute this (if the name actually matches). substitute this (if the name actually matches).
*/ */
#ifdef HAVE_THREAD_LOCAL
_Py_thread_local const char *pkgcontext = NULL; _Py_thread_local const char *pkgcontext = NULL;
# undef PKGCONTEXT # undef PKGCONTEXT
# define PKGCONTEXT pkgcontext # define PKGCONTEXT pkgcontext
#endif
const char * const char *
_PyImport_ResolveNameWithPackageContext(const char *name) _PyImport_ResolveNameWithPackageContext(const char *name)
{ {
#ifndef HAVE_THREAD_LOCAL
PyMutex_Lock(&EXTENSIONS.mutex);
#endif
if (PKGCONTEXT != NULL) { if (PKGCONTEXT != NULL) {
const char *p = strrchr(PKGCONTEXT, '.'); const char *p = strrchr(PKGCONTEXT, '.');
if (p != NULL && strcmp(name, p+1) == 0) { if (p != NULL && strcmp(name, p+1) == 0) {
@ -801,23 +796,14 @@ _PyImport_ResolveNameWithPackageContext(const char *name)
PKGCONTEXT = NULL; PKGCONTEXT = NULL;
} }
} }
#ifndef HAVE_THREAD_LOCAL
PyMutex_Unlock(&EXTENSIONS.mutex);
#endif
return name; return name;
} }
const char * const char *
_PyImport_SwapPackageContext(const char *newcontext) _PyImport_SwapPackageContext(const char *newcontext)
{ {
#ifndef HAVE_THREAD_LOCAL
PyMutex_Lock(&EXTENSIONS.mutex);
#endif
const char *oldcontext = PKGCONTEXT; const char *oldcontext = PKGCONTEXT;
PKGCONTEXT = newcontext; PKGCONTEXT = newcontext;
#ifndef HAVE_THREAD_LOCAL
PyMutex_Unlock(&EXTENSIONS.mutex);
#endif
return oldcontext; return oldcontext;
} }

View file

@ -67,9 +67,6 @@ to avoid the expense of doing their own locking).
For each of these functions, the GIL must be held by the current thread. For each of these functions, the GIL must be held by the current thread.
*/ */
#ifndef HAVE_THREAD_LOCAL
# error "no supported thread-local variable storage classifier"
#endif
/* The attached thread state for the current thread. */ /* The attached thread state for the current thread. */
_Py_thread_local PyThreadState *_Py_tss_tstate = NULL; _Py_thread_local PyThreadState *_Py_tss_tstate = NULL;