Skip to content

Commit 5f55067

Browse files
gh-81057: Move More Globals in Core Code to _PyRuntimeState (gh-99516)
#81057
1 parent 5cfb7d1 commit 5f55067

24 files changed

+240
-129
lines changed

Include/cpython/modsupport.h

-2
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,3 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg(
106106
(minpos), (maxpos), (minkw), (buf)))
107107

108108
PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(PyModuleDef*, int apiver);
109-
110-
PyAPI_DATA(const char *) _Py_PackageContext;

Include/internal/pycore_fileutils.h

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ extern "C" {
1010

1111
#include <locale.h> /* struct lconv */
1212

13+
14+
struct _fileutils_state {
15+
int force_ascii;
16+
};
17+
1318
typedef enum {
1419
_Py_ERROR_UNKNOWN=0,
1520
_Py_ERROR_STRICT,

Include/internal/pycore_floatobject.h

+12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ extern void _PyFloat_FiniType(PyInterpreterState *);
1919

2020
/* other API */
2121

22+
enum _py_float_format_type {
23+
_py_float_format_unknown,
24+
_py_float_format_ieee_big_endian,
25+
_py_float_format_ieee_little_endian,
26+
};
27+
28+
struct _Py_float_runtime_state {
29+
enum _py_float_format_type float_format;
30+
enum _py_float_format_type double_format;
31+
};
32+
33+
2234
#ifndef WITH_FREELISTS
2335
// without freelists
2436
# define PyFloat_MAXFREELIST 0

Include/internal/pycore_import.h

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct _import_runtime_state {
3232
_PyTime_t accumulated;
3333
int header;
3434
} find_and_load;
35+
/* Package context -- the full module name for package imports */
36+
const char * pkgcontext;
3537
};
3638

3739

Include/internal/pycore_interp.h

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern "C" {
2828

2929

3030
struct _pending_calls {
31+
int busy;
3132
PyThread_type_lock lock;
3233
/* Request for running pending calls. */
3334
_Py_atomic_int calls_to_do;

Include/internal/pycore_pyhash.h

+31-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,36 @@
55
# error "this header requires Py_BUILD_CORE define"
66
#endif
77

8-
uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
98

9+
struct pyhash_runtime_state {
10+
struct {
11+
#ifndef MS_WINDOWS
12+
int fd;
13+
dev_t st_dev;
14+
ino_t st_ino;
15+
#else
16+
// This is a placeholder so the struct isn't empty on Windows.
17+
int _not_used;
18+
#endif
19+
} urandom_cache;
20+
};
21+
22+
#ifndef MS_WINDOWS
23+
# define _py_urandom_cache_INIT \
24+
{ \
25+
.fd = -1, \
26+
}
27+
#else
28+
# define _py_urandom_cache_INIT {0}
1029
#endif
30+
31+
#define pyhash_state_INIT \
32+
{ \
33+
.urandom_cache = _py_urandom_cache_INIT, \
34+
}
35+
36+
37+
uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
38+
39+
40+
#endif // Py_INTERNAL_HASH_H

Include/internal/pycore_pylifecycle.h

-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ extern "C" {
1414
struct _PyArgv;
1515
struct pyruntimestate;
1616

17-
/* True if the main interpreter thread exited due to an unhandled
18-
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
19-
PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
20-
2117
extern int _Py_SetFileSystemEncoding(
2218
const char *encoding,
2319
const char *errors);

Include/internal/pycore_runtime.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ extern "C" {
1010

1111
#include "pycore_atomic.h" /* _Py_atomic_address */
1212
#include "pycore_dtoa.h" // struct _dtoa_runtime_state
13+
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
1314
#include "pycore_gil.h" // struct _gil_runtime_state
1415
#include "pycore_global_objects.h" // struct _Py_global_objects
1516
#include "pycore_import.h" // struct _import_runtime_state
1617
#include "pycore_interp.h" // PyInterpreterState
1718
#include "pycore_pymem.h" // struct _pymem_allocators
19+
#include "pycore_pyhash.h" // struct pyhash_runtime_state
1820
#include "pycore_obmalloc.h" // struct obmalloc_state
1921
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
2022

@@ -92,6 +94,12 @@ typedef struct pyruntimestate {
9294

9395
struct _pymem_allocators allocators;
9496
struct _obmalloc_state obmalloc;
97+
struct pyhash_runtime_state pyhash_state;
98+
struct {
99+
/* True if the main interpreter thread exited due to an unhandled
100+
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
101+
int unhandled_keyboard_interrupt;
102+
} signals;
95103

96104
struct pyinterpreters {
97105
PyThread_type_lock mutex;
@@ -131,6 +139,7 @@ typedef struct pyruntimestate {
131139
struct _PyTraceMalloc_Config config;
132140
} tracemalloc;
133141
struct _dtoa_runtime_state dtoa;
142+
struct _fileutils_state fileutils;
134143

135144
PyPreConfig preconfig;
136145

@@ -140,7 +149,8 @@ typedef struct pyruntimestate {
140149
void *open_code_userdata;
141150
_Py_AuditHookEntry *audit_hook_head;
142151

143-
struct _Py_unicode_runtime_ids unicode_ids;
152+
struct _Py_float_runtime_state float_state;
153+
struct _Py_unicode_runtime_state unicode_state;
144154

145155
struct {
146156
/* Used to set PyTypeObject.tp_version_tag */

Include/internal/pycore_runtime_init.h

+21-13
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,18 @@ extern "C" {
1919

2020
#define _PyRuntimeState_INIT(runtime) \
2121
{ \
22-
.gilstate = { \
23-
.check_enabled = 1, \
24-
/* A TSS key must be initialized with Py_tss_NEEDS_INIT \
25-
in accordance with the specification. */ \
26-
.autoTSSkey = Py_tss_NEEDS_INIT, \
27-
}, \
2822
.allocators = { \
2923
_pymem_allocators_standard_INIT(runtime), \
3024
_pymem_allocators_debug_INIT, \
3125
_pymem_allocators_obj_arena_INIT, \
3226
}, \
3327
.obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
28+
.pyhash_state = pyhash_state_INIT, \
3429
.interpreters = { \
3530
/* This prevents interpreters from getting created \
3631
until _PyInterpreterState_Enable() is called. */ \
3732
.next_id = -1, \
3833
}, \
39-
.tracemalloc = { \
40-
.config = _PyTraceMalloc_Config_INIT, \
41-
}, \
42-
.dtoa = _dtoa_runtime_state_INIT(runtime), \
43-
.types = { \
44-
.next_version_tag = 1, \
45-
}, \
4634
.imports = { \
4735
.lock = { \
4836
.mutex = NULL, \
@@ -53,6 +41,26 @@ extern "C" {
5341
.header = 1, \
5442
}, \
5543
}, \
44+
.gilstate = { \
45+
.check_enabled = 1, \
46+
/* A TSS key must be initialized with Py_tss_NEEDS_INIT \
47+
in accordance with the specification. */ \
48+
.autoTSSkey = Py_tss_NEEDS_INIT, \
49+
}, \
50+
.tracemalloc = { \
51+
.config = _PyTraceMalloc_Config_INIT, \
52+
}, \
53+
.dtoa = _dtoa_runtime_state_INIT(runtime), \
54+
.fileutils = { \
55+
.force_ascii = -1, \
56+
}, \
57+
.float_state = { \
58+
.float_format = _py_float_format_unknown, \
59+
.double_format = _py_float_format_unknown, \
60+
}, \
61+
.types = { \
62+
.next_version_tag = 1, \
63+
}, \
5664
.global_objects = { \
5765
.singletons = { \
5866
.small_ints = _Py_small_ints_INIT, \

Include/internal/pycore_unicodeobject.h

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ struct _Py_unicode_runtime_ids {
3131
Py_ssize_t next_index;
3232
};
3333

34+
struct _Py_unicode_runtime_state {
35+
struct _Py_unicode_runtime_ids ids;
36+
};
37+
3438
/* fs_codec.encoding is initialized to NULL.
3539
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
3640
struct _Py_unicode_fs_codec {

Modules/main.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,10 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
296296
Py_DECREF(module);
297297
return pymain_exit_err_print();
298298
}
299-
_Py_UnhandledKeyboardInterrupt = 0;
299+
_PyRuntime.signals.unhandled_keyboard_interrupt = 0;
300300
result = PyObject_Call(runmodule, runargs, NULL);
301301
if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
302-
_Py_UnhandledKeyboardInterrupt = 1;
302+
_PyRuntime.signals.unhandled_keyboard_interrupt = 1;
303303
}
304304
Py_DECREF(runpy);
305305
Py_DECREF(runmodule);
@@ -696,7 +696,7 @@ Py_RunMain(void)
696696

697697
pymain_free();
698698

699-
if (_Py_UnhandledKeyboardInterrupt) {
699+
if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
700700
exitcode = exit_sigint();
701701
}
702702

Objects/floatobject.c

+17-10
Original file line numberDiff line numberDiff line change
@@ -1723,12 +1723,14 @@ float___getnewargs___impl(PyObject *self)
17231723
}
17241724

17251725
/* this is for the benefit of the pack/unpack routines below */
1726+
typedef enum _py_float_format_type float_format_type;
1727+
#define unknown_format _py_float_format_unknown
1728+
#define ieee_big_endian_format _py_float_format_ieee_big_endian
1729+
#define ieee_little_endian_format _py_float_format_ieee_little_endian
17261730

1727-
typedef enum {
1728-
unknown_format, ieee_big_endian_format, ieee_little_endian_format
1729-
} float_format_type;
1731+
#define float_format (_PyRuntime.float_state.float_format)
1732+
#define double_format (_PyRuntime.float_state.double_format)
17301733

1731-
static float_format_type double_format, float_format;
17321734

17331735
/*[clinic input]
17341736
@classmethod
@@ -1929,13 +1931,9 @@ PyTypeObject PyFloat_Type = {
19291931
.tp_vectorcall = (vectorcallfunc)float_vectorcall,
19301932
};
19311933

1932-
void
1933-
_PyFloat_InitState(PyInterpreterState *interp)
1934+
static void
1935+
_init_global_state(void)
19341936
{
1935-
if (!_Py_IsMainInterpreter(interp)) {
1936-
return;
1937-
}
1938-
19391937
float_format_type detected_double_format, detected_float_format;
19401938

19411939
/* We attempt to determine if this machine is using IEEE
@@ -1985,6 +1983,15 @@ _PyFloat_InitState(PyInterpreterState *interp)
19851983
float_format = detected_float_format;
19861984
}
19871985

1986+
void
1987+
_PyFloat_InitState(PyInterpreterState *interp)
1988+
{
1989+
if (!_Py_IsMainInterpreter(interp)) {
1990+
return;
1991+
}
1992+
_init_global_state();
1993+
}
1994+
19881995
PyStatus
19891996
_PyFloat_InitTypes(PyInterpreterState *interp)
19901997
{

Objects/moduleobject.c

+2
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,15 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
218218
_Py_PackageContext, and PyModule_Create*() will substitute this
219219
(if the name actually matches).
220220
*/
221+
#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
221222
if (_Py_PackageContext != NULL) {
222223
const char *p = strrchr(_Py_PackageContext, '.');
223224
if (p != NULL && strcmp(module->m_name, p+1) == 0) {
224225
name = _Py_PackageContext;
225226
_Py_PackageContext = NULL;
226227
}
227228
}
229+
#undef _Py_PackageContext
228230
if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
229231
return NULL;
230232

Objects/unicodeobject.c

+15-4
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,7 @@ _PyUnicode_FromId(_Py_Identifier *id)
18561856

18571857
Py_ssize_t index = _Py_atomic_size_get(&id->index);
18581858
if (index < 0) {
1859-
struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_ids;
1859+
struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_state.ids;
18601860

18611861
PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK);
18621862
// Check again to detect concurrent access. Another thread can have
@@ -14491,12 +14491,14 @@ PyTypeObject PyUnicode_Type = {
1449114491

1449214492
/* Initialize the Unicode implementation */
1449314493

14494-
void
14495-
_PyUnicode_InitState(PyInterpreterState *interp)
14494+
static void
14495+
_init_global_state(void)
1449614496
{
14497-
if (!_Py_IsMainInterpreter(interp)) {
14497+
static int initialized = 0;
14498+
if (initialized) {
1449814499
return;
1449914500
}
14501+
initialized = 1;
1450014502

1450114503
/* initialize the linebreak bloom filter */
1450214504
const Py_UCS2 linebreak[] = {
@@ -14514,6 +14516,15 @@ _PyUnicode_InitState(PyInterpreterState *interp)
1451414516
Py_ARRAY_LENGTH(linebreak));
1451514517
}
1451614518

14519+
void
14520+
_PyUnicode_InitState(PyInterpreterState *interp)
14521+
{
14522+
if (!_Py_IsMainInterpreter(interp)) {
14523+
return;
14524+
}
14525+
_init_global_state();
14526+
}
14527+
1451714528

1451814529
PyStatus
1451914530
_PyUnicode_InitGlobalObjects(PyInterpreterState *interp)

Python/bootstrap_hash.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "Python.h"
22
#include "pycore_initconfig.h"
33
#include "pycore_fileutils.h" // _Py_fstat_noraise()
4+
#include "pycore_runtime.h" // _PyRuntime
45

56
#ifdef MS_WINDOWS
67
# include <windows.h>
@@ -263,11 +264,7 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
263264
#endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
264265

265266

266-
static struct {
267-
int fd;
268-
dev_t st_dev;
269-
ino_t st_ino;
270-
} urandom_cache = { -1 };
267+
#define urandom_cache (_PyRuntime.pyhash_state.urandom_cache)
271268

272269
/* Read random bytes from the /dev/urandom device:
273270
@@ -402,6 +399,9 @@ dev_urandom_close(void)
402399
urandom_cache.fd = -1;
403400
}
404401
}
402+
403+
#undef urandom_cache
404+
405405
#endif /* !MS_WINDOWS */
406406

407407

0 commit comments

Comments
 (0)