Skip to content

Commit c5fa8a5

Browse files
authored
gh-112535: Add test on _Py_ThreadId() (#112709)
Add also test.support.Py_GIL_DISABLED constant.
1 parent a8ce149 commit c5fa8a5

File tree

6 files changed

+75
-8
lines changed

6 files changed

+75
-8
lines changed

Lib/test/support/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,8 @@ def check_cflags_pgo():
796796
return any(option in cflags_nodist for option in pgo_options)
797797

798798

799-
if sysconfig.get_config_var('Py_GIL_DISABLED'):
799+
Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED'))
800+
if Py_GIL_DISABLED:
800801
_header = 'PHBBInP'
801802
else:
802803
_header = 'nP'

Lib/test/test_capi/test_misc.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2854,5 +2854,60 @@ def testfunc(n, m):
28542854
self.assertIn("_FOR_ITER_TIER_TWO", uops)
28552855

28562856

2857+
@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED')
2858+
class TestPyThreadId(unittest.TestCase):
2859+
def test_py_thread_id(self):
2860+
# gh-112535: Test _Py_ThreadId(): make sure that thread identifiers
2861+
# in a few threads are unique
2862+
py_thread_id = _testinternalcapi.py_thread_id
2863+
short_sleep = 0.010
2864+
2865+
class GetThreadId(threading.Thread):
2866+
def __init__(self):
2867+
super().__init__()
2868+
self.get_lock = threading.Lock()
2869+
self.get_lock.acquire()
2870+
self.started_lock = threading.Event()
2871+
self.py_tid = None
2872+
2873+
def run(self):
2874+
self.started_lock.set()
2875+
self.get_lock.acquire()
2876+
self.py_tid = py_thread_id()
2877+
time.sleep(short_sleep)
2878+
self.py_tid2 = py_thread_id()
2879+
2880+
nthread = 5
2881+
threads = [GetThreadId() for _ in range(nthread)]
2882+
2883+
# first make run sure that all threads are running
2884+
for thread in threads:
2885+
thread.start()
2886+
for thread in threads:
2887+
thread.started_lock.wait()
2888+
2889+
# call _Py_ThreadId() in the main thread
2890+
py_thread_ids = [py_thread_id()]
2891+
2892+
# now call _Py_ThreadId() in each thread
2893+
for thread in threads:
2894+
thread.get_lock.release()
2895+
2896+
# call _Py_ThreadId() in each thread and wait until threads complete
2897+
for thread in threads:
2898+
thread.join()
2899+
py_thread_ids.append(thread.py_tid)
2900+
# _PyThread_Id() should not change for a given thread.
2901+
# For example, it should remain the same after a short sleep.
2902+
self.assertEqual(thread.py_tid2, thread.py_tid)
2903+
2904+
# make sure that all _Py_ThreadId() are unique
2905+
for tid in py_thread_ids:
2906+
self.assertIsInstance(tid, int)
2907+
self.assertGreater(tid, 0)
2908+
self.assertEqual(len(set(py_thread_ids)), len(py_thread_ids),
2909+
py_thread_ids)
2910+
2911+
28572912
if __name__ == "__main__":
28582913
unittest.main()

Lib/test/test_cppext/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# compatible with C++ and does not emit C++ compiler warnings.
33
import os.path
44
import shutil
5-
import sys
65
import unittest
76
import subprocess
87
import sysconfig
@@ -15,7 +14,7 @@
1514

1615
# gh-110119: pip does not currently support 't' in the ABI flag use by
1716
# --disable-gil builds. Once it does, we can remove this skip.
18-
@unittest.skipIf(sysconfig.get_config_var('Py_GIL_DISABLED') == 1,
17+
@unittest.skipIf(support.Py_GIL_DISABLED,
1918
'test does not work with --disable-gil')
2019
@support.requires_subprocess()
2120
class TestCPPExt(unittest.TestCase):

Lib/test/test_importlib/test_windows.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import os
55
import re
66
import sys
7-
import sysconfig
87
import unittest
8+
from test import support
99
from test.support import import_helper
1010
from contextlib import contextmanager
1111
from test.test_importlib.util import temp_module
@@ -112,7 +112,7 @@ def test_module_not_found(self):
112112
class WindowsExtensionSuffixTests:
113113
def test_tagged_suffix(self):
114114
suffixes = self.machinery.EXTENSION_SUFFIXES
115-
abi_flags = "t" if sysconfig.get_config_var("Py_GIL_DISABLED") else ""
115+
abi_flags = "t" if support.Py_GIL_DISABLED else ""
116116
ver = sys.version_info
117117
platform = re.sub('[^a-zA-Z0-9]', '_', get_platform())
118118
expected_tag = f".cp{ver.major}{ver.minor}{abi_flags}-{platform}.pyd"

Lib/test/test_sys.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,9 +1224,7 @@ def test_pystats(self):
12241224
@test.support.cpython_only
12251225
@unittest.skipUnless(hasattr(sys, 'abiflags'), 'need sys.abiflags')
12261226
def test_disable_gil_abi(self):
1227-
abi_threaded = 't' in sys.abiflags
1228-
py_gil_disabled = (sysconfig.get_config_var('Py_GIL_DISABLED') == 1)
1229-
self.assertEqual(py_gil_disabled, abi_threaded)
1227+
self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED)
12301228

12311229

12321230
@test.support.cpython_only

Modules/_testinternalcapi.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,17 @@ get_type_module_name(PyObject *self, PyObject *type)
16251625
}
16261626

16271627

1628+
#ifdef Py_GIL_DISABLED
1629+
static PyObject *
1630+
get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1631+
{
1632+
uintptr_t tid = _Py_ThreadId();
1633+
Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(tid));
1634+
return PyLong_FromUnsignedLongLong(tid);
1635+
}
1636+
#endif
1637+
1638+
16281639
static PyMethodDef module_functions[] = {
16291640
{"get_configs", get_configs, METH_NOARGS},
16301641
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1688,6 +1699,9 @@ static PyMethodDef module_functions[] = {
16881699
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
16891700
_TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF
16901701
{"get_type_module_name", get_type_module_name, METH_O},
1702+
#ifdef Py_GIL_DISABLED
1703+
{"py_thread_id", get_py_thread_id, METH_NOARGS},
1704+
#endif
16911705
{NULL, NULL} /* sentinel */
16921706
};
16931707

0 commit comments

Comments
 (0)