gh-116322: Add Py_mod_gil module slot by swtaarrs · Pull Request #116882 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fa92cb4
Add Py_mod_gil module slot
swtaarrs Mar 12, 2024
7edf796
Merge remote-tracking branch 'upstream/main' into cpython-mod-gil
swtaarrs Mar 22, 2024
450aa41
Some review comments from Eric
swtaarrs Mar 27, 2024
6bbd281
Merge remote-tracking branch 'upstream/main' into cpython-mod-gil
swtaarrs Apr 3, 2024
47b9e26
Fix enabling the GIL, also support disabling the GIL
swtaarrs Apr 15, 2024
f7c3e50
Merge remote-tracking branch 'upstream/main' into cpython-mod-gil
swtaarrs Apr 15, 2024
6c198e4
Fix module size in test_objecttypes
swtaarrs Apr 15, 2024
554c5b4
Add missing : in Py_mod_gil documentation
swtaarrs Apr 15, 2024
cd187a0
Merge remote-tracking branch 'upstream/main' into cpython-mod-gil
swtaarrs Apr 23, 2024
8057478
From Eric: better loop, move _PyImport_CheckGILForModule
swtaarrs Apr 23, 2024
a8f0943
Merge remote-tracking branch 'upstream/main' into cpython-mod-gil
swtaarrs Apr 26, 2024
bbb949e
Remove code to enable/disable the GIL (it will go in a different PR)
swtaarrs Apr 30, 2024
7f1205e
Don't put PyModule_SetGIL() in the limited API
swtaarrs Apr 26, 2024
f8b02b3
Set m->md_gil in PyModule_FromDefAndSpec2, rename/guard PyModule_SetG…
swtaarrs May 1, 2024
d2bad05
Fix limited API version for Py_mod_gil
swtaarrs May 1, 2024
d7d59f0
Update NEWS entry for behavioral changes
swtaarrs Apr 30, 2024
ccd6e00
Mark all modules as not using GIL
swtaarrs May 1, 2024
8846586
Merge remote-tracking branch 'upstream/main' into HEAD
swtaarrs May 1, 2024
99bc5cb
Fix 'gil_slot set but not used' warning
swtaarrs May 1, 2024
6882c13
Patch generator for Python-ast.c instead of just the file itself
swtaarrs May 1, 2024
da63df1
Update limited API version for _scproxy.c
swtaarrs May 1, 2024
2998def
Fix _testconsole.c for Windows build
swtaarrs May 1, 2024
77d1652
Fix winsound.c for Windows build
swtaarrs May 2, 2024
d1fe0cc
Mark more modules as not using the GIL
swtaarrs May 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Doc/c-api/module.rst
3 changes: 3 additions & 0 deletions Include/internal/pycore_moduleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ typedef struct {
PyObject *md_weaklist;
// for logging purposes after md_dict is cleared
PyObject *md_name;
#ifdef Py_GIL_DISABLED
void *md_gil;
#endif
Comment thread
ericsnowcurrently marked this conversation as resolved.
} PyModuleObject;

static inline PyModuleDef* _PyModule_GetDef(PyObject *mod) {
Expand Down
16 changes: 15 additions & 1 deletion Include/moduleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ struct PyModuleDef_Slot {
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030c0000
# define Py_mod_multiple_interpreters 3
#endif
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000
# define Py_mod_gil 4
#endif


#ifndef Py_LIMITED_API
#define _Py_mod_LAST_SLOT 3
#define _Py_mod_LAST_SLOT 4
#endif

#endif /* New in 3.5 */
Expand All @@ -90,6 +94,16 @@ struct PyModuleDef_Slot {
# define Py_MOD_PER_INTERPRETER_GIL_SUPPORTED ((void *)2)
#endif

/* for Py_mod_gil: */
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000
# define Py_MOD_GIL_USED ((void *)0)
# define Py_MOD_GIL_NOT_USED ((void *)1)
#endif

#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED)
PyAPI_FUNC(int) PyModule_ExperimentalSetGIL(PyObject *module, void *gil);
#endif

struct PyModuleDef {
PyModuleDef_Base m_base;
const char* m_name;
Expand Down
44 changes: 44 additions & 0 deletions Lib/test/test_importlib/extension/_test_nonmodule_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import types
import unittest
from test.test_importlib import util

machinery = util.import_importlib('importlib.machinery')

from test.test_importlib.extension.test_loader import MultiPhaseExtensionModuleTests


class NonModuleExtensionTests:
setUp = MultiPhaseExtensionModuleTests.setUp
load_module_by_name = MultiPhaseExtensionModuleTests.load_module_by_name

def _test_nonmodule(self):
# Test returning a non-module object from create works.
name = self.name + '_nonmodule'
mod = self.load_module_by_name(name)
self.assertNotEqual(type(mod), type(unittest))
self.assertEqual(mod.three, 3)

# issue 27782
def test_nonmodule_with_methods(self):
# Test creating a non-module object with methods defined.
name = self.name + '_nonmodule_with_methods'
mod = self.load_module_by_name(name)
self.assertNotEqual(type(mod), type(unittest))
self.assertEqual(mod.three, 3)
self.assertEqual(mod.bar(10, 1), 9)

def test_null_slots(self):
# Test that NULL slots aren't a problem.
name = self.name + '_null_slots'
module = self.load_module_by_name(name)
self.assertIsInstance(module, types.ModuleType)
self.assertEqual(module.__name__, name)


(Frozen_NonModuleExtensionTests,
Source_NonModuleExtensionTests
) = util.test_both(NonModuleExtensionTests, machinery=machinery)


if __name__ == '__main__':
unittest.main()
35 changes: 11 additions & 24 deletions Lib/test/test_importlib/extension/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import warnings
import importlib.util
import importlib
from test.support import MISSING_C_DOCSTRINGS
from test import support
from test.support import MISSING_C_DOCSTRINGS, script_helper


class LoaderTests:
Expand Down Expand Up @@ -325,29 +326,6 @@ def test_unloadable_nonascii(self):
self.load_module_by_name(name)
self.assertEqual(cm.exception.name, name)

def test_nonmodule(self):
# Test returning a non-module object from create works.
name = self.name + '_nonmodule'
mod = self.load_module_by_name(name)
self.assertNotEqual(type(mod), type(unittest))
self.assertEqual(mod.three, 3)

# issue 27782
def test_nonmodule_with_methods(self):
# Test creating a non-module object with methods defined.
name = self.name + '_nonmodule_with_methods'
mod = self.load_module_by_name(name)
self.assertNotEqual(type(mod), type(unittest))
self.assertEqual(mod.three, 3)
self.assertEqual(mod.bar(10, 1), 9)

def test_null_slots(self):
# Test that NULL slots aren't a problem.
name = self.name + '_null_slots'
module = self.load_module_by_name(name)
self.assertIsInstance(module, types.ModuleType)
self.assertEqual(module.__name__, name)

def test_bad_modules(self):
# Test SystemError is raised for misbehaving extensions.
for name_base in [
Expand Down Expand Up @@ -401,5 +379,14 @@ def test_nonascii(self):
) = util.test_both(MultiPhaseExtensionModuleTests, machinery=machinery)


class NonModuleExtensionTests(unittest.TestCase):
def test_nonmodule_cases(self):
# The test cases in this file cause the GIL to be enabled permanently
# in free-threaded builds, so they are run in a subprocess to isolate
# this effect.
script = support.findfile("test_importlib/extension/_test_nonmodule_cases.py")
script_helper.run_test_script(script)


if __name__ == '__main__':
unittest.main()
5 changes: 4 additions & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,10 @@ def get_gen(): yield 1
check(int(PyLong_BASE**2-1), vsize('') + 2*self.longdigit)
check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit)
# module
check(unittest, size('PnPPP'))
if support.Py_GIL_DISABLED:
check(unittest, size('PPPPPP'))
else:
check(unittest, size('PPPPP'))
# None
check(None, size(''))
# NotImplementedType
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Extension modules may indicate to the runtime that they can run without the
GIL. Multi-phase init modules do so by calling providing
``Py_MOD_GIL_NOT_USED`` for the ``Py_mod_gil`` slot, while single-phase init
modules call ``PyModule_ExperimentalSetGIL(mod, Py_MOD_GIL_NOT_USED)`` from
their init function.
1 change: 1 addition & 0 deletions Modules/_abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ _abcmodule_free(void *module)
static PyModuleDef_Slot _abcmodule_slots[] = {
{Py_mod_exec, _abcmodule_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3795,6 +3795,7 @@ module_exec(PyObject *mod)
static struct PyModuleDef_Slot module_slots[] = {
{Py_mod_exec, module_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL},
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_bisectmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ bisect_modexec(PyObject *m)
static PyModuleDef_Slot bisect_slots[] = {
{Py_mod_exec, bisect_modexec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_blake2/blake2module.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ blake2_exec(PyObject *m)
static PyModuleDef_Slot _blake2_slots[] = {
{Py_mod_exec, blake2_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_bz2module.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ _bz2_free(void *module)
static struct PyModuleDef_Slot _bz2_slots[] = {
{Py_mod_exec, _bz2_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_codecsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ static PyMethodDef _codecs_functions[] = {

static PyModuleDef_Slot _codecs_slots[] = {
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2817,6 +2817,7 @@ collections_exec(PyObject *module) {
static struct PyModuleDef_Slot collections_slots[] = {
{Py_mod_exec, collections_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_contextvarsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ _contextvars_exec(PyObject *m)
static struct PyModuleDef_Slot _contextvars_slots[] = {
{Py_mod_exec, _contextvars_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1796,6 +1796,7 @@ csv_exec(PyObject *module) {
static PyModuleDef_Slot csv_slots[] = {
{Py_mod_exec, csv_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -5948,6 +5948,7 @@ module_free(void *module)
static PyModuleDef_Slot module_slots[] = {
{Py_mod_exec, _ctypes_mod_exec},
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
5 changes: 3 additions & 2 deletions Modules/_ctypes/_ctypes_test.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
// Need limited C API version 3.13 for Py_mod_gil
#include "pyconfig.h" // Py_GIL_DISABLED
#ifndef Py_GIL_DISABLED
# define Py_LIMITED_API 0x030c0000
# define Py_LIMITED_API 0x030d0000
#endif

// gh-85283: On Windows, Py_LIMITED_API requires Py_BUILD_CORE to not attempt
Expand Down Expand Up @@ -1167,6 +1167,7 @@ _testfunc_pylist_append(PyObject *list, PyObject *item)

static struct PyModuleDef_Slot _ctypes_test_slots[] = {
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_curses_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ static PyModuleDef_Slot _curses_slots[] = {
// XXX gh-103092: fix isolation.
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
//{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
3 changes: 3 additions & 0 deletions Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -4743,6 +4743,9 @@ PyInit__curses(void)
m = PyModule_Create(&_cursesmodule);
if (m == NULL)
return NULL;
#ifdef Py_GIL_DISABLED
PyModule_ExperimentalSetGIL(m, Py_MOD_GIL_NOT_USED);
#endif

/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
Expand Down
3 changes: 3 additions & 0 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6984,6 +6984,9 @@ PyInit__datetime(void)
PyObject *mod = PyModule_Create(&datetimemodule);
if (mod == NULL)
return NULL;
#ifdef Py_GIL_DISABLED
PyModule_ExperimentalSetGIL(mod, Py_MOD_GIL_NOT_USED);
#endif

if (_datetime_exec(mod) < 0) {
Py_DECREF(mod);
Expand Down
1 change: 1 addition & 0 deletions Modules/_dbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ _dbm_module_free(void *module)
static PyModuleDef_Slot _dbmmodule_slots[] = {
{Py_mod_exec, _dbm_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_decimal/_decimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6157,6 +6157,7 @@ decimal_free(void *module)
static struct PyModuleDef_Slot _decimal_slots[] = {
{Py_mod_exec, _decimal_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL},
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4463,6 +4463,7 @@ module_exec(PyObject *m)
static struct PyModuleDef_Slot elementtree_slots[] = {
{Py_mod_exec, module_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL},
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_functoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,7 @@ _functools_free(void *module)
static struct PyModuleDef_Slot _functools_slots[] = {
{Py_mod_exec, _functools_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_gdbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,7 @@ _gdbm_module_free(void *module)
static PyModuleDef_Slot _gdbm_module_slots[] = {
{Py_mod_exec, _gdbm_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2289,6 +2289,7 @@ static PyModuleDef_Slot hashlib_slots[] = {
{Py_mod_exec, hashlib_init_constructors},
{Py_mod_exec, hashlib_exception},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};

Expand Down
1 change: 1 addition & 0 deletions Modules/_heapqmodule.c
Loading