mirror of
https://github.com/python/cpython.git
synced 2025-11-25 12:44:13 +00:00
bpo-45953: Statically allocate the main interpreter (and initial thread state). (gh-29883)
Previously, the main interpreter was allocated on the heap during runtime initialization. Here we instead embed it into _PyRuntimeState, which means it is statically allocated as part of the _PyRuntime global. The same goes for the initial thread state (of each interpreter, including the main one). Consequently there are fewer allocations during runtime/interpreter init, fewer possible failures, and better memory locality. FYI, this also helps efforts to consolidate globals, which in turns helps work on subinterpreter isolation. https://bugs.python.org/issue45953
This commit is contained in:
parent
0bbf30e2b9
commit
ed57b36c32
8 changed files with 115 additions and 34 deletions
|
|
@ -11,8 +11,10 @@ extern "C" {
|
|||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||
#include "pycore_gil.h" // struct _gil_runtime_state
|
||||
#include "pycore_global_objects.h" // struct _Py_global_objects
|
||||
#include "pycore_interp.h" // struct _is
|
||||
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
|
||||
|
||||
|
||||
/* ceval state */
|
||||
|
||||
struct _ceval_runtime_state {
|
||||
|
|
@ -53,6 +55,9 @@ typedef struct _Py_AuditHookEntry {
|
|||
|
||||
/* Full Python runtime state */
|
||||
|
||||
/* _PyRuntimeState holds the global state for the CPython runtime.
|
||||
That data is exposed in the internal API as a static variable (_PyRuntime).
|
||||
*/
|
||||
typedef struct pyruntimestate {
|
||||
/* Has been initialized to a safe state.
|
||||
|
||||
|
|
@ -81,7 +86,11 @@ typedef struct pyruntimestate {
|
|||
|
||||
struct pyinterpreters {
|
||||
PyThread_type_lock mutex;
|
||||
/* The linked list of interpreters, newest first. */
|
||||
PyInterpreterState *head;
|
||||
/* The runtime's initial interpreter, which has a special role
|
||||
in the operation of the runtime. It is also often the only
|
||||
interpreter. */
|
||||
PyInterpreterState *main;
|
||||
/* _next_interp_id is an auto-numbered sequence of small
|
||||
integers. It gets initialized in _PyInterpreterState_Init(),
|
||||
|
|
@ -118,25 +127,44 @@ typedef struct pyruntimestate {
|
|||
|
||||
struct _Py_unicode_runtime_ids unicode_ids;
|
||||
|
||||
/* All the objects that are shared by the runtime's interpreters. */
|
||||
struct _Py_global_objects global_objects;
|
||||
// If anything gets added after global_objects then
|
||||
// _PyRuntimeState_reset() needs to get updated to clear it.
|
||||
|
||||
/* The following fields are here to avoid allocation during init.
|
||||
The data is exposed through _PyRuntimeState pointer fields.
|
||||
These fields should not be accessed directly outside of init.
|
||||
|
||||
All other _PyRuntimeState pointer fields are populated when
|
||||
needed and default to NULL.
|
||||
|
||||
For now there are some exceptions to that rule, which require
|
||||
allocation during init. These will be addressed on a case-by-case
|
||||
basis. Most notably, we don't pre-allocated the several mutex
|
||||
(PyThread_type_lock) fields, because on Windows we only ever get
|
||||
a pointer type.
|
||||
*/
|
||||
|
||||
/* PyInterpreterState.interpreters.main */
|
||||
PyInterpreterState _main_interpreter;
|
||||
} _PyRuntimeState;
|
||||
|
||||
#define _PyThreadState_INIT \
|
||||
{ \
|
||||
._static = 1, \
|
||||
}
|
||||
#define _PyInterpreterState_INIT \
|
||||
{ \
|
||||
._static = 1, \
|
||||
._initial_thread = _PyThreadState_INIT, \
|
||||
}
|
||||
#define _PyRuntimeState_INIT \
|
||||
{ \
|
||||
.global_objects = _Py_global_objects_INIT, \
|
||||
._main_interpreter = _PyInterpreterState_INIT, \
|
||||
}
|
||||
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
|
||||
|
||||
static inline void
|
||||
_PyRuntimeState_reset(_PyRuntimeState *runtime)
|
||||
{
|
||||
/* Make it match _PyRuntimeState_INIT. */
|
||||
memset(runtime, 0, (size_t)&runtime->global_objects - (size_t)runtime);
|
||||
_Py_global_objects_reset(&runtime->global_objects);
|
||||
}
|
||||
|
||||
/* other API */
|
||||
|
||||
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue