py/modsys: Add sys.implementation._thread attribute.

This is useful to distinguish between GIL and non-GIL builds.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George
2025-07-15 13:32:55 +10:00
parent e993f53877
commit 18f2e94846
3 changed files with 36 additions and 4 deletions

View File

@@ -77,6 +77,8 @@ Constants
* *_mpy* - supported mpy file-format version (optional attribute)
* *_build* - string that can help identify the configuration that
MicroPython was built with
* *_thread* - optional string attribute, exists if the target has threading
and is either "GIL" or "unsafe"
This object is the recommended way to distinguish MicroPython from other
Python implementations (note that it still may not exist in the very
@@ -95,6 +97,14 @@ Constants
* On microcontroller targets, the first element is the board name and the second
element (if present) is the board variant, for example ``'RPI_PICO2-RISCV'``
The *_thread* entry was added in version 1.26.0 and if it exists then the
target has the ``_thread`` module. If the target enables the GIL (global
interpreter lock) then this attribute is ``"GIL"``. Otherwise the attribute
is ``"unsafe"`` and the target has threading but does not enable the GIL,
and mutable Python objects (such as `bytearray`, `list` and `dict`) that are
shared amongst threads must be protected explicitly by locks such as
``_thread.allocate_lock``.
.. admonition:: Difference to CPython
:class: attention

View File

@@ -103,6 +103,18 @@ static const MP_DEFINE_STR_OBJ(mp_sys_implementation__build_obj, MICROPY_BOARD_B
#define SYS_IMPLEMENTATION_ELEMS__BUILD
#endif
#if MICROPY_PY_THREAD
#if MICROPY_PY_THREAD_GIL
#define SYS_IMPLEMENTATION_ELEMS__THREAD \
, MP_ROM_QSTR(MP_QSTR_GIL)
#else
#define SYS_IMPLEMENTATION_ELEMS__THREAD \
, MP_ROM_QSTR(MP_QSTR_unsafe)
#endif
#else
#define SYS_IMPLEMENTATION_ELEMS__THREAD
#endif
#if MICROPY_PREVIEW_VERSION_2
#define SYS_IMPLEMENTATION_ELEMS__V2 \
, MP_ROM_TRUE
@@ -120,6 +132,9 @@ static const qstr impl_fields[] = {
#if defined(MICROPY_BOARD_BUILD_NAME)
MP_QSTR__build,
#endif
#if MICROPY_PY_THREAD
MP_QSTR__thread,
#endif
#if MICROPY_PREVIEW_VERSION_2
MP_QSTR__v2,
#endif
@@ -127,20 +142,21 @@ static const qstr impl_fields[] = {
static MP_DEFINE_ATTRTUPLE(
mp_sys_implementation_obj,
impl_fields,
3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_BOARD_BUILD + MICROPY_PREVIEW_VERSION_2,
3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_BOARD_BUILD + MICROPY_PY_THREAD + MICROPY_PREVIEW_VERSION_2,
SYS_IMPLEMENTATION_ELEMS_BASE
SYS_IMPLEMENTATION_ELEMS__MPY
SYS_IMPLEMENTATION_ELEMS__BUILD
SYS_IMPLEMENTATION_ELEMS__THREAD
SYS_IMPLEMENTATION_ELEMS__V2
);
#else
static const mp_rom_obj_tuple_t mp_sys_implementation_obj = {
{&mp_type_tuple},
3 + MICROPY_PERSISTENT_CODE_LOAD,
// Do not include SYS_IMPLEMENTATION_ELEMS__BUILD or SYS_IMPLEMENTATION_ELEMS__V2
// because SYS_IMPLEMENTATION_ELEMS__MPY may be empty if
// Do not include SYS_IMPLEMENTATION_ELEMS__BUILD, SYS_IMPLEMENTATION_ELEMS__THREAD
// or SYS_IMPLEMENTATION_ELEMS__V2 because SYS_IMPLEMENTATION_ELEMS__MPY may be empty if
// MICROPY_PERSISTENT_CODE_LOAD is disabled, which means they'll share
// the same index. Cannot query _build or _v2 if MICROPY_PY_ATTRTUPLE is
// the same index. Cannot query _build, _thread or _v2 if MICROPY_PY_ATTRTUPLE is
// disabled.
{
SYS_IMPLEMENTATION_ELEMS_BASE

View File

@@ -30,6 +30,12 @@ else:
# Effectively skip subtests
print(str)
if hasattr(sys.implementation, '_thread'):
print(sys.implementation._thread in ("GIL", "unsafe"))
else:
# Effectively skip subtests
print(True)
try:
print(sys.intern('micropython') == 'micropython')
has_intern = True