aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-12-04 23:40:06 +0100
committerGitHub <noreply@github.com>2023-12-04 22:40:06 +0000
commitc5fa8a54dbdf564d482e2e3857aa3efa61edd329 (patch)
tree9ccea9297f4d21823ea5ed7fb045f1d97b3ce988
parenta8ce149628c9eaafb8c38fbf25fbd1ed483d2902 (diff)
downloadcpython-c5fa8a54dbdf564d482e2e3857aa3efa61edd329.tar.gz
cpython-c5fa8a54dbdf564d482e2e3857aa3efa61edd329.zip
gh-112535: Add test on _Py_ThreadId() (#112709)
Add also test.support.Py_GIL_DISABLED constant.
-rw-r--r--Lib/test/support/__init__.py3
-rw-r--r--Lib/test/test_capi/test_misc.py55
-rw-r--r--Lib/test/test_cppext/__init__.py3
-rw-r--r--Lib/test/test_importlib/test_windows.py4
-rw-r--r--Lib/test/test_sys.py4
-rw-r--r--Modules/_testinternalcapi.c14
6 files changed, 75 insertions, 8 deletions
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 318a0599a75..c22d73c231b 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -796,7 +796,8 @@ def check_cflags_pgo():
return any(option in cflags_nodist for option in pgo_options)
-if sysconfig.get_config_var('Py_GIL_DISABLED'):
+Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED'))
+if Py_GIL_DISABLED:
_header = 'PHBBInP'
else:
_header = 'nP'
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 6cbf5d22203..3d86ae37190 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -2854,5 +2854,60 @@ class TestUops(unittest.TestCase):
self.assertIn("_FOR_ITER_TIER_TWO", uops)
+@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED')
+class TestPyThreadId(unittest.TestCase):
+ def test_py_thread_id(self):
+ # gh-112535: Test _Py_ThreadId(): make sure that thread identifiers
+ # in a few threads are unique
+ py_thread_id = _testinternalcapi.py_thread_id
+ short_sleep = 0.010
+
+ class GetThreadId(threading.Thread):
+ def __init__(self):
+ super().__init__()
+ self.get_lock = threading.Lock()
+ self.get_lock.acquire()
+ self.started_lock = threading.Event()
+ self.py_tid = None
+
+ def run(self):
+ self.started_lock.set()
+ self.get_lock.acquire()
+ self.py_tid = py_thread_id()
+ time.sleep(short_sleep)
+ self.py_tid2 = py_thread_id()
+
+ nthread = 5
+ threads = [GetThreadId() for _ in range(nthread)]
+
+ # first make run sure that all threads are running
+ for thread in threads:
+ thread.start()
+ for thread in threads:
+ thread.started_lock.wait()
+
+ # call _Py_ThreadId() in the main thread
+ py_thread_ids = [py_thread_id()]
+
+ # now call _Py_ThreadId() in each thread
+ for thread in threads:
+ thread.get_lock.release()
+
+ # call _Py_ThreadId() in each thread and wait until threads complete
+ for thread in threads:
+ thread.join()
+ py_thread_ids.append(thread.py_tid)
+ # _PyThread_Id() should not change for a given thread.
+ # For example, it should remain the same after a short sleep.
+ self.assertEqual(thread.py_tid2, thread.py_tid)
+
+ # make sure that all _Py_ThreadId() are unique
+ for tid in py_thread_ids:
+ self.assertIsInstance(tid, int)
+ self.assertGreater(tid, 0)
+ self.assertEqual(len(set(py_thread_ids)), len(py_thread_ids),
+ py_thread_ids)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py
index 299a16ada2e..c6039bd17b0 100644
--- a/Lib/test/test_cppext/__init__.py
+++ b/Lib/test/test_cppext/__init__.py
@@ -2,7 +2,6 @@
# compatible with C++ and does not emit C++ compiler warnings.
import os.path
import shutil
-import sys
import unittest
import subprocess
import sysconfig
@@ -15,7 +14,7 @@ SETUP = os.path.join(os.path.dirname(__file__), 'setup.py')
# gh-110119: pip does not currently support 't' in the ABI flag use by
# --disable-gil builds. Once it does, we can remove this skip.
-@unittest.skipIf(sysconfig.get_config_var('Py_GIL_DISABLED') == 1,
+@unittest.skipIf(support.Py_GIL_DISABLED,
'test does not work with --disable-gil')
@support.requires_subprocess()
class TestCPPExt(unittest.TestCase):
diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py
index d25133240b1..8a9a8fffcd1 100644
--- a/Lib/test/test_importlib/test_windows.py
+++ b/Lib/test/test_importlib/test_windows.py
@@ -4,8 +4,8 @@ machinery = test_util.import_importlib('importlib.machinery')
import os
import re
import sys
-import sysconfig
import unittest
+from test import support
from test.support import import_helper
from contextlib import contextmanager
from test.test_importlib.util import temp_module
@@ -112,7 +112,7 @@ class WindowsRegistryFinderTests:
class WindowsExtensionSuffixTests:
def test_tagged_suffix(self):
suffixes = self.machinery.EXTENSION_SUFFIXES
- abi_flags = "t" if sysconfig.get_config_var("Py_GIL_DISABLED") else ""
+ abi_flags = "t" if support.Py_GIL_DISABLED else ""
ver = sys.version_info
platform = re.sub('[^a-zA-Z0-9]', '_', get_platform())
expected_tag = f".cp{ver.major}{ver.minor}{abi_flags}-{platform}.pyd"
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 8c2c1a40f74..db5ba16c4d9 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1224,9 +1224,7 @@ class SysModuleTest(unittest.TestCase):
@test.support.cpython_only
@unittest.skipUnless(hasattr(sys, 'abiflags'), 'need sys.abiflags')
def test_disable_gil_abi(self):
- abi_threaded = 't' in sys.abiflags
- py_gil_disabled = (sysconfig.get_config_var('Py_GIL_DISABLED') == 1)
- self.assertEqual(py_gil_disabled, abi_threaded)
+ self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED)
@test.support.cpython_only
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 4607a3faf17..ba7653f2d9c 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1625,6 +1625,17 @@ get_type_module_name(PyObject *self, PyObject *type)
}
+#ifdef Py_GIL_DISABLED
+static PyObject *
+get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ uintptr_t tid = _Py_ThreadId();
+ Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(tid));
+ return PyLong_FromUnsignedLongLong(tid);
+}
+#endif
+
+
static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1688,6 +1699,9 @@ static PyMethodDef module_functions[] = {
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
_TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF
{"get_type_module_name", get_type_module_name, METH_O},
+#ifdef Py_GIL_DISABLED
+ {"py_thread_id", get_py_thread_id, METH_NOARGS},
+#endif
{NULL, NULL} /* sentinel */
};