mirror of
https://github.com/python/cpython.git
synced 2026-05-30 22:30:44 +00:00
gh-146636: abi3t: Define Py_GIL_DISABLED but do not use it (GH-148142)
When compiling for abi3t, define Py_GIL_DISABLED, so that users who check it to enable additional locking aren't broken. But also avoid using Py_GIL_DISABLED in Python headers themselves -- abi3 and abi3t ought to be the same except the _Py_OPAQUE_PYOBJECT differences. A check for this is coming in a later PR. It will require rewriting some preprocessor conditions, some of these changes are included in this PR. For _Py_IsOwnedByCurrentThread & supporting functions I opted to move them to a cpython/ header, as they're rather self-contained.
This commit is contained in:
parent
5e9d90b615
commit
fbc1a5b076
5 changed files with 115 additions and 96 deletions
|
|
@ -495,3 +495,82 @@ PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *);
|
|||
PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *);
|
||||
|
||||
PyAPI_FUNC(int) PyUnstable_SetImmortal(PyObject *op);
|
||||
|
||||
#if defined(Py_GIL_DISABLED)
|
||||
PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void);
|
||||
|
||||
static inline uintptr_t
|
||||
_Py_ThreadId(void)
|
||||
{
|
||||
uintptr_t tid;
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
tid = __readgsqword(48);
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
tid = __readfsdword(24);
|
||||
#elif defined(_MSC_VER) && defined(_M_ARM64)
|
||||
tid = __getReg(18);
|
||||
#elif defined(__MINGW32__) && defined(_M_X64)
|
||||
tid = __readgsqword(48);
|
||||
#elif defined(__MINGW32__) && defined(_M_IX86)
|
||||
tid = __readfsdword(24);
|
||||
#elif defined(__MINGW32__) && defined(_M_ARM64)
|
||||
tid = __getReg(18);
|
||||
#elif defined(__i386__)
|
||||
__asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS
|
||||
#elif defined(__MACH__) && defined(__x86_64__)
|
||||
__asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS
|
||||
#elif defined(__x86_64__)
|
||||
__asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS
|
||||
#elif defined(__arm__) && __ARM_ARCH >= 7
|
||||
__asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid));
|
||||
#elif defined(__aarch64__) && defined(__APPLE__)
|
||||
__asm__ ("mrs %0, tpidrro_el0" : "=r" (tid));
|
||||
#elif defined(__aarch64__)
|
||||
__asm__ ("mrs %0, tpidr_el0" : "=r" (tid));
|
||||
#elif defined(__powerpc64__)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// r13 is reserved for use as system thread ID by the Power 64-bit ABI.
|
||||
register uintptr_t tp __asm__ ("r13");
|
||||
__asm__("" : "=r" (tp));
|
||||
tid = tp;
|
||||
#endif
|
||||
#elif defined(__powerpc__)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// r2 is reserved for use as system thread ID by the Power 32-bit ABI.
|
||||
register uintptr_t tp __asm__ ("r2");
|
||||
__asm__ ("" : "=r" (tp));
|
||||
tid = tp;
|
||||
#endif
|
||||
#elif defined(__s390__) && defined(__GNUC__)
|
||||
// Both GCC and Clang have supported __builtin_thread_pointer
|
||||
// for s390 from long time ago.
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#elif defined(__riscv)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// tp is Thread Pointer provided by the RISC-V ABI.
|
||||
__asm__ ("mv %0, tp" : "=r" (tid));
|
||||
#endif
|
||||
#else
|
||||
// Fallback to a portable implementation if we do not have a faster
|
||||
// platform-specific implementation.
|
||||
tid = _Py_GetThreadLocal_Addr();
|
||||
#endif
|
||||
return tid;
|
||||
}
|
||||
|
||||
static inline Py_ALWAYS_INLINE int
|
||||
_Py_IsOwnedByCurrentThread(PyObject *ob)
|
||||
{
|
||||
#ifdef _Py_THREAD_SANITIZER
|
||||
return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId();
|
||||
#else
|
||||
return ob->ob_tid == _Py_ThreadId();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,8 +113,10 @@ struct PyModuleDef_Slot {
|
|||
# define Py_MOD_GIL_NOT_USED ((void *)1)
|
||||
#endif
|
||||
|
||||
#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED)
|
||||
#if !defined(Py_LIMITED_API)
|
||||
# if defined(Py_GIL_DISABLED)
|
||||
PyAPI_FUNC(int) PyUnstable_Module_SetGIL(PyObject *module, void *gil);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
|
||||
|
|
|
|||
|
|
@ -186,85 +186,6 @@ typedef struct PyVarObject PyVarObject;
|
|||
PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
|
||||
#define Py_Is(x, y) ((x) == (y))
|
||||
|
||||
#if defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API)
|
||||
PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void);
|
||||
|
||||
static inline uintptr_t
|
||||
_Py_ThreadId(void)
|
||||
{
|
||||
uintptr_t tid;
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
tid = __readgsqword(48);
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
tid = __readfsdword(24);
|
||||
#elif defined(_MSC_VER) && defined(_M_ARM64)
|
||||
tid = __getReg(18);
|
||||
#elif defined(__MINGW32__) && defined(_M_X64)
|
||||
tid = __readgsqword(48);
|
||||
#elif defined(__MINGW32__) && defined(_M_IX86)
|
||||
tid = __readfsdword(24);
|
||||
#elif defined(__MINGW32__) && defined(_M_ARM64)
|
||||
tid = __getReg(18);
|
||||
#elif defined(__i386__)
|
||||
__asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS
|
||||
#elif defined(__MACH__) && defined(__x86_64__)
|
||||
__asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS
|
||||
#elif defined(__x86_64__)
|
||||
__asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS
|
||||
#elif defined(__arm__) && __ARM_ARCH >= 7
|
||||
__asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid));
|
||||
#elif defined(__aarch64__) && defined(__APPLE__)
|
||||
__asm__ ("mrs %0, tpidrro_el0" : "=r" (tid));
|
||||
#elif defined(__aarch64__)
|
||||
__asm__ ("mrs %0, tpidr_el0" : "=r" (tid));
|
||||
#elif defined(__powerpc64__)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// r13 is reserved for use as system thread ID by the Power 64-bit ABI.
|
||||
register uintptr_t tp __asm__ ("r13");
|
||||
__asm__("" : "=r" (tp));
|
||||
tid = tp;
|
||||
#endif
|
||||
#elif defined(__powerpc__)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// r2 is reserved for use as system thread ID by the Power 32-bit ABI.
|
||||
register uintptr_t tp __asm__ ("r2");
|
||||
__asm__ ("" : "=r" (tp));
|
||||
tid = tp;
|
||||
#endif
|
||||
#elif defined(__s390__) && defined(__GNUC__)
|
||||
// Both GCC and Clang have supported __builtin_thread_pointer
|
||||
// for s390 from long time ago.
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#elif defined(__riscv)
|
||||
#if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer)
|
||||
tid = (uintptr_t)__builtin_thread_pointer();
|
||||
#else
|
||||
// tp is Thread Pointer provided by the RISC-V ABI.
|
||||
__asm__ ("mv %0, tp" : "=r" (tid));
|
||||
#endif
|
||||
#else
|
||||
// Fallback to a portable implementation if we do not have a faster
|
||||
// platform-specific implementation.
|
||||
tid = _Py_GetThreadLocal_Addr();
|
||||
#endif
|
||||
return tid;
|
||||
}
|
||||
|
||||
static inline Py_ALWAYS_INLINE int
|
||||
_Py_IsOwnedByCurrentThread(PyObject *ob)
|
||||
{
|
||||
#ifdef _Py_THREAD_SANITIZER
|
||||
return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId();
|
||||
#else
|
||||
return ob->ob_tid == _Py_ThreadId();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
PyAPI_DATA(PyTypeObject) PyLong_Type;
|
||||
PyAPI_DATA(PyTypeObject) PyBool_Type;
|
||||
|
||||
|
|
@ -652,8 +573,10 @@ given type object has a specified feature.
|
|||
#define _Py_IMMORTAL_FLAGS (1 << 0)
|
||||
#define _Py_LEGACY_ABI_CHECK_FLAG (1 << 1) /* see PyModuleDef_Init() */
|
||||
#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2)
|
||||
#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG)
|
||||
#define _Py_TYPE_REVEALED_FLAG (1 << 3)
|
||||
#if !defined(Py_LIMITED_API)
|
||||
# if defined(Py_GIL_DISABLED) && defined(Py_DEBUG)
|
||||
# define _Py_TYPE_REVEALED_FLAG (1 << 3)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define Py_CONSTANT_NONE 0
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@
|
|||
# define Py_BUILD_CORE
|
||||
#endif
|
||||
|
||||
#if defined(Py_TARGET_ABI3T)
|
||||
# if !defined(Py_GIL_DISABLED)
|
||||
// Define Py_GIL_DISABLED for users' needs. This macro is used to enable
|
||||
// locking needed in for free-threaded interpreters builds.
|
||||
# define Py_GIL_DISABLED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Symbols and macros to supply platform-independent interfaces to basic
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
#if !defined(_Py_OPAQUE_PYOBJECT)
|
||||
/*
|
||||
Immortalization:
|
||||
|
||||
|
|
@ -90,14 +91,16 @@ check by comparing the reference count field to the minimum immortality refcount
|
|||
# define _Py_REF_SHARED(refcnt, flags) \
|
||||
(((refcnt) << _Py_REF_SHARED_SHIFT) + (flags))
|
||||
#endif // Py_GIL_DISABLED
|
||||
|
||||
#endif // _Py_OPAQUE_PYOBJECT
|
||||
|
||||
// Py_REFCNT() implementation for the stable ABI
|
||||
PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
|
||||
|
||||
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030e0000
|
||||
// Stable ABI implements Py_REFCNT() as a function call
|
||||
// on limited C API version 3.14 and newer.
|
||||
// on limited C API version 3.14 and newer, and on abi3t.
|
||||
#elif defined(_Py_OPAQUE_PYOBJECT)
|
||||
// Py_REFCNT() is also a function call in abi3t.
|
||||
#else
|
||||
static inline Py_ssize_t _Py_REFCNT(PyObject *ob) {
|
||||
#if !defined(Py_GIL_DISABLED)
|
||||
|
|
@ -150,9 +153,10 @@ PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt);
|
|||
|
||||
static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
|
||||
assert(refcnt >= 0);
|
||||
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000
|
||||
#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000) \
|
||||
|| defined(_Py_OPAQUE_PYOBJECT)
|
||||
// Stable ABI implements Py_SET_REFCNT() as a function call
|
||||
// on limited C API version 3.13 and newer.
|
||||
// on limited C API version 3.13 and newer, and abi3t.
|
||||
_Py_SetRefcnt(ob, refcnt);
|
||||
#else
|
||||
// This immortal check is for code that is unaware of immortal objects.
|
||||
|
|
@ -191,7 +195,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
|
|||
ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
|
||||
}
|
||||
#endif // Py_GIL_DISABLED
|
||||
#endif // Py_LIMITED_API+0 < 0x030d0000
|
||||
#endif // Py_LIMITED_API
|
||||
}
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
|
||||
# define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt))
|
||||
|
|
@ -250,10 +254,11 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *);
|
|||
|
||||
static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
|
||||
{
|
||||
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
|
||||
#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \
|
||||
|| defined(_Py_OPAQUE_PYOBJECT)
|
||||
// Stable ABI implements Py_INCREF() as a function call on limited C API
|
||||
// version 3.12 and newer, and on Python built in debug mode. _Py_IncRef()
|
||||
// was added to Python 3.10.0a7, use Py_IncRef() on older Python versions.
|
||||
// version 3.12 and newer, abi3t, and on Python built in debug mode.
|
||||
// _Py_IncRef() was added to Python 3.10.0a7, use Py_IncRef() on older versions.
|
||||
// Py_IncRef() accepts NULL whereas _Py_IncRef() doesn't.
|
||||
# if Py_LIMITED_API+0 >= 0x030a00A7
|
||||
_Py_IncRef(op);
|
||||
|
|
@ -305,8 +310,8 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
|
|||
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED)
|
||||
#if !defined(Py_LIMITED_API)
|
||||
#if defined(Py_GIL_DISABLED)
|
||||
// Implements Py_DECREF on objects not owned by the current thread.
|
||||
PyAPI_FUNC(void) _Py_DecRefShared(PyObject *);
|
||||
PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int);
|
||||
|
|
@ -316,12 +321,14 @@ PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int);
|
|||
// zero. Otherwise, the thread gives up ownership and merges the reference
|
||||
// count fields.
|
||||
PyAPI_FUNC(void) _Py_MergeZeroLocalRefcount(PyObject *);
|
||||
#endif
|
||||
#endif // Py_GIL_DISABLED
|
||||
#endif // Py_LIMITED_API
|
||||
|
||||
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
|
||||
#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \
|
||||
|| defined(_Py_OPAQUE_PYOBJECT)
|
||||
// Stable ABI implements Py_DECREF() as a function call on limited C API
|
||||
// version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was
|
||||
// added to Python 3.10.0a7, use Py_DecRef() on older Python versions.
|
||||
// version 3.12 and newer, abi3t, and on Python built in debug mode.
|
||||
// _Py_DecRef() was added to Python 3.10.0a7, use Py_DecRef() on older versions.
|
||||
// Py_DecRef() accepts NULL whereas _Py_DecRef() doesn't.
|
||||
static inline void Py_DECREF(PyObject *op) {
|
||||
# if Py_LIMITED_API+0 >= 0x030a00A7
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue