gh-112535: Add test on _Py_ThreadId() (#112709)

Add also test.support.Py_GIL_DISABLED constant.
This commit is contained in:
Victor Stinner 2023-12-04 23:40:06 +01:00 committed by GitHub
parent a8ce149628
commit c5fa8a54db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 8 deletions

View file

@ -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'

View file

@ -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()

View file

@ -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):

View file

@ -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"

View file

@ -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

View file

@ -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 */
};