Skip to content

Commit a4dd662

Browse files
authored
pythongh-140550: Use a bool for the Py_mod_gil value (pythonGH-141519)
This needs a single bit, but was stored as a void* in the module struct. This didn't matter due to packing, but now that there's another bool in the struct, we can save a bit of memory by making md_gil a bool. Variables that changed type are renamed, to detect conflicts.
1 parent 4885ecf commit a4dd662

File tree

4 files changed

+24
-21
lines changed

4 files changed

+24
-21
lines changed

Include/internal/pycore_moduleobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ typedef struct {
3030
PyObject *md_name;
3131
bool md_token_is_def; /* if true, `md_token` is the PyModuleDef */
3232
#ifdef Py_GIL_DISABLED
33-
void *md_gil;
33+
bool md_requires_gil;
3434
#endif
3535
Py_ssize_t md_state_size;
3636
traverseproc md_state_traverse;

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1725,7 +1725,7 @@ def get_gen(): yield 1
17251725
check(int(PyLong_BASE**2), vsize('') + 3*self.longdigit)
17261726
# module
17271727
if support.Py_GIL_DISABLED:
1728-
md_gil = 'P'
1728+
md_gil = '?'
17291729
else:
17301730
md_gil = ''
17311731
check(unittest, size('PPPP?' + md_gil + 'NPPPPP'))

Objects/moduleobject.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ new_module_notrack(PyTypeObject *mt)
178178
m->md_name = NULL;
179179
m->md_token_is_def = false;
180180
#ifdef Py_GIL_DISABLED
181-
m->md_gil = Py_MOD_GIL_USED;
181+
m->md_requires_gil = true;
182182
#endif
183183
m->md_state_size = 0;
184184
m->md_state_traverse = NULL;
@@ -361,7 +361,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
361361
m->md_token_is_def = true;
362362
module_copy_members_from_deflike(m, module);
363363
#ifdef Py_GIL_DISABLED
364-
m->md_gil = Py_MOD_GIL_USED;
364+
m->md_requires_gil = true;
365365
#endif
366366
return (PyObject*)m;
367367
}
@@ -380,7 +380,7 @@ module_from_def_and_spec(
380380
int has_multiple_interpreters_slot = 0;
381381
void *multiple_interpreters = (void *)0;
382382
int has_gil_slot = 0;
383-
void *gil_slot = Py_MOD_GIL_USED;
383+
bool requires_gil = true;
384384
int has_execution_slots = 0;
385385
const char *name;
386386
int ret;
@@ -474,7 +474,7 @@ module_from_def_and_spec(
474474
name);
475475
goto error;
476476
}
477-
gil_slot = cur_slot->value;
477+
requires_gil = (cur_slot->value != Py_MOD_GIL_NOT_USED);
478478
has_gil_slot = 1;
479479
break;
480480
case Py_mod_abi:
@@ -581,9 +581,9 @@ module_from_def_and_spec(
581581
mod->md_token = token;
582582
}
583583
#ifdef Py_GIL_DISABLED
584-
mod->md_gil = gil_slot;
584+
mod->md_requires_gil = requires_gil;
585585
#else
586-
(void)gil_slot;
586+
(void)requires_gil;
587587
#endif
588588
mod->md_exec = m_exec;
589589
} else {
@@ -664,11 +664,12 @@ PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *slots, PyObject *spec)
664664
int
665665
PyUnstable_Module_SetGIL(PyObject *module, void *gil)
666666
{
667+
bool requires_gil = (gil != Py_MOD_GIL_NOT_USED);
667668
if (!PyModule_Check(module)) {
668669
PyErr_BadInternalCall();
669670
return -1;
670671
}
671-
((PyModuleObject *)module)->md_gil = gil;
672+
((PyModuleObject *)module)->md_requires_gil = requires_gil;
672673
return 0;
673674
}
674675
#endif

Python/import.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,9 +1017,10 @@ struct extensions_cache_value {
10171017
_Py_ext_module_origin origin;
10181018

10191019
#ifdef Py_GIL_DISABLED
1020-
/* The module's md_gil slot, for legacy modules that are reinitialized from
1021-
m_dict rather than calling their initialization function again. */
1022-
void *md_gil;
1020+
/* The module's md_requires_gil member, for legacy modules that are
1021+
* reinitialized from m_dict rather than calling their initialization
1022+
* function again. */
1023+
bool md_requires_gil;
10231024
#endif
10241025
};
10251026

@@ -1350,7 +1351,7 @@ static struct extensions_cache_value *
13501351
_extensions_cache_set(PyObject *path, PyObject *name,
13511352
PyModuleDef *def, PyModInitFunction m_init,
13521353
Py_ssize_t m_index, PyObject *m_dict,
1353-
_Py_ext_module_origin origin, void *md_gil)
1354+
_Py_ext_module_origin origin, bool requires_gil)
13541355
{
13551356
struct extensions_cache_value *value = NULL;
13561357
void *key = NULL;
@@ -1405,11 +1406,11 @@ _extensions_cache_set(PyObject *path, PyObject *name,
14051406
/* m_dict is set by set_cached_m_dict(). */
14061407
.origin=origin,
14071408
#ifdef Py_GIL_DISABLED
1408-
.md_gil=md_gil,
1409+
.md_requires_gil=requires_gil,
14091410
#endif
14101411
};
14111412
#ifndef Py_GIL_DISABLED
1412-
(void)md_gil;
1413+
(void)requires_gil;
14131414
#endif
14141415
if (init_cached_m_dict(newvalue, m_dict) < 0) {
14151416
goto finally;
@@ -1547,7 +1548,8 @@ _PyImport_CheckGILForModule(PyObject* module, PyObject *module_name)
15471548
}
15481549

15491550
if (!PyModule_Check(module) ||
1550-
((PyModuleObject *)module)->md_gil == Py_MOD_GIL_USED) {
1551+
((PyModuleObject *)module)->md_requires_gil)
1552+
{
15511553
if (_PyEval_EnableGILPermanent(tstate)) {
15521554
int warn_result = PyErr_WarnFormat(
15531555
PyExc_RuntimeWarning,
@@ -1725,7 +1727,7 @@ struct singlephase_global_update {
17251727
Py_ssize_t m_index;
17261728
PyObject *m_dict;
17271729
_Py_ext_module_origin origin;
1728-
void *md_gil;
1730+
bool md_requires_gil;
17291731
};
17301732

17311733
static struct extensions_cache_value *
@@ -1784,7 +1786,7 @@ update_global_state_for_extension(PyThreadState *tstate,
17841786
#endif
17851787
cached = _extensions_cache_set(
17861788
path, name, def, m_init, singlephase->m_index, m_dict,
1787-
singlephase->origin, singlephase->md_gil);
1789+
singlephase->origin, singlephase->md_requires_gil);
17881790
if (cached == NULL) {
17891791
// XXX Ignore this error? Doing so would effectively
17901792
// mark the module as not loadable.
@@ -1873,7 +1875,7 @@ reload_singlephase_extension(PyThreadState *tstate,
18731875
if (def->m_base.m_copy != NULL) {
18741876
// For non-core modules, fetch the GIL slot that was stored by
18751877
// import_run_extension().
1876-
((PyModuleObject *)mod)->md_gil = cached->md_gil;
1878+
((PyModuleObject *)mod)->md_requires_gil = cached->md_requires_gil;
18771879
}
18781880
#endif
18791881
/* We can't set mod->md_def if it's missing,
@@ -2128,7 +2130,7 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
21282130
.m_index=def->m_base.m_index,
21292131
.origin=info->origin,
21302132
#ifdef Py_GIL_DISABLED
2131-
.md_gil=((PyModuleObject *)mod)->md_gil,
2133+
.md_requires_gil=((PyModuleObject *)mod)->md_requires_gil,
21322134
#endif
21332135
};
21342136
// gh-88216: Extensions and def->m_base.m_copy can be updated
@@ -2323,7 +2325,7 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name,
23232325
.origin=_Py_ext_module_origin_CORE,
23242326
#ifdef Py_GIL_DISABLED
23252327
/* Unused when m_dict == NULL. */
2326-
.md_gil=NULL,
2328+
.md_requires_gil=false,
23272329
#endif
23282330
};
23292331
cached = update_global_state_for_extension(

0 commit comments

Comments
 (0)