]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-81057: Move More Globals in Core Code to _PyRuntimeState (gh-99516)
authorEric Snow <ericsnowcurrently@gmail.com>
Wed, 16 Nov 2022 16:37:14 +0000 (09:37 -0700)
committerGitHub <noreply@github.com>
Wed, 16 Nov 2022 16:37:14 +0000 (09:37 -0700)
https://github.com/python/cpython/issues/81057

24 files changed:
Include/cpython/modsupport.h
Include/internal/pycore_fileutils.h
Include/internal/pycore_floatobject.h
Include/internal/pycore_import.h
Include/internal/pycore_interp.h
Include/internal/pycore_pyhash.h
Include/internal/pycore_pylifecycle.h
Include/internal/pycore_runtime.h
Include/internal/pycore_runtime_init.h
Include/internal/pycore_unicodeobject.h
Modules/main.c
Objects/floatobject.c
Objects/moduleobject.c
Objects/unicodeobject.c
Python/bootstrap_hash.c
Python/ceval_gil.c
Python/fileutils.c
Python/importdl.c
Python/modsupport.c
Python/pylifecycle.c
Python/pystate.c
Python/pythonrun.c
Tools/c-analyzer/cpython/globals-to-fix.tsv
Tools/c-analyzer/cpython/ignored.tsv

index d8458923b3fab8fc37afbbcb0e2e9b24a368d793..88f34fe7513bf20507aaf43437248d2760a290d1 100644 (file)
@@ -106,5 +106,3 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg(
                            (minpos), (maxpos), (minkw), (buf)))
 
 PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(PyModuleDef*, int apiver);
-
-PyAPI_DATA(const char *) _Py_PackageContext;
index 3ce8108e4e04f158afc732c5dbd8b9e5b774032f..ac89c43d569c07eaaa80ffc4a2fb00aadcd6d176 100644 (file)
@@ -10,6 +10,11 @@ extern "C" {
 
 #include <locale.h>   /* struct lconv */
 
+
+struct _fileutils_state {
+    int force_ascii;
+};
+
 typedef enum {
     _Py_ERROR_UNKNOWN=0,
     _Py_ERROR_STRICT,
index 8a655543329f33546cd7c8b30d4728c45e086c8b..27c63bc87f3ee3035a741388b2def513118f561c 100644 (file)
@@ -19,6 +19,18 @@ extern void _PyFloat_FiniType(PyInterpreterState *);
 
 /* other API */
 
+enum _py_float_format_type {
+    _py_float_format_unknown,
+    _py_float_format_ieee_big_endian,
+    _py_float_format_ieee_little_endian,
+};
+
+struct _Py_float_runtime_state {
+    enum _py_float_format_type float_format;
+    enum _py_float_format_type double_format;
+};
+
+
 #ifndef WITH_FREELISTS
 // without freelists
 #  define PyFloat_MAXFREELIST 0
index 8ba9666cdcf9a9caface825c6589b80d35f8fb2c..9036dff6725330a037b625a273df4bfb8053616c 100644 (file)
@@ -32,6 +32,8 @@ struct _import_runtime_state {
         _PyTime_t accumulated;
         int header;
     } find_and_load;
+    /* Package context -- the full module name for package imports */
+    const char * pkgcontext;
 };
 
 
index a13bc32e11449075ccc1e83c314239525ff88fc6..b7fc4b480d7f80640e369bb2e2ae83c35c12e01d 100644 (file)
@@ -28,6 +28,7 @@ extern "C" {
 
 
 struct _pending_calls {
+    int busy;
     PyThread_type_lock lock;
     /* Request for running pending calls. */
     _Py_atomic_int calls_to_do;
index a229f8d8b7f0a2ab0bf9120fcc301cc5c74594c8..34dfa53771288ee66f4b7f9d86ceacdc00014f76 100644 (file)
@@ -5,6 +5,36 @@
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
-uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
 
+struct pyhash_runtime_state {
+    struct {
+#ifndef MS_WINDOWS
+        int fd;
+        dev_t st_dev;
+        ino_t st_ino;
+#else
+    // This is a placeholder so the struct isn't empty on Windows.
+    int _not_used;
+#endif
+    } urandom_cache;
+};
+
+#ifndef MS_WINDOWS
+# define _py_urandom_cache_INIT \
+    { \
+        .fd = -1, \
+    }
+#else
+# define _py_urandom_cache_INIT {0}
 #endif
+
+#define pyhash_state_INIT \
+    { \
+        .urandom_cache = _py_urandom_cache_INIT, \
+    }
+
+
+uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
+
+
+#endif  // Py_INTERNAL_HASH_H
index 359b809d5870a1cde08fd908c42e1ed500c7dafe..4c0ffa7a9b1ab75c462b0ba68ec7ca6389a57c73 100644 (file)
@@ -14,10 +14,6 @@ extern "C" {
 struct _PyArgv;
 struct pyruntimestate;
 
-/* True if the main interpreter thread exited due to an unhandled
- * KeyboardInterrupt exception, suggesting the user pressed ^C. */
-PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
-
 extern int _Py_SetFileSystemEncoding(
     const char *encoding,
     const char *errors);
index 8b2b9d7a85b231cf6c328d9f8dba304aa134473a..f8b988021b9992a3c32fe34f5a6d76b45a4b3b24 100644 (file)
@@ -10,11 +10,13 @@ extern "C" {
 
 #include "pycore_atomic.h"          /* _Py_atomic_address */
 #include "pycore_dtoa.h"            // struct _dtoa_runtime_state
+#include "pycore_floatobject.h"     // struct _Py_float_runtime_state
 #include "pycore_gil.h"             // struct _gil_runtime_state
 #include "pycore_global_objects.h"  // struct _Py_global_objects
 #include "pycore_import.h"          // struct _import_runtime_state
 #include "pycore_interp.h"          // PyInterpreterState
 #include "pycore_pymem.h"           // struct _pymem_allocators
+#include "pycore_pyhash.h"          // struct pyhash_runtime_state
 #include "pycore_obmalloc.h"        // struct obmalloc_state
 #include "pycore_unicodeobject.h"   // struct _Py_unicode_runtime_ids
 
@@ -92,6 +94,12 @@ typedef struct pyruntimestate {
 
     struct _pymem_allocators allocators;
     struct _obmalloc_state obmalloc;
+    struct pyhash_runtime_state pyhash_state;
+    struct {
+        /* True if the main interpreter thread exited due to an unhandled
+         * KeyboardInterrupt exception, suggesting the user pressed ^C. */
+        int unhandled_keyboard_interrupt;
+    } signals;
 
     struct pyinterpreters {
         PyThread_type_lock mutex;
@@ -131,6 +139,7 @@ typedef struct pyruntimestate {
         struct _PyTraceMalloc_Config config;
     } tracemalloc;
     struct _dtoa_runtime_state dtoa;
+    struct _fileutils_state fileutils;
 
     PyPreConfig preconfig;
 
@@ -140,7 +149,8 @@ typedef struct pyruntimestate {
     void *open_code_userdata;
     _Py_AuditHookEntry *audit_hook_head;
 
-    struct _Py_unicode_runtime_ids unicode_ids;
+    struct _Py_float_runtime_state float_state;
+    struct _Py_unicode_runtime_state unicode_state;
 
     struct {
         /* Used to set PyTypeObject.tp_version_tag */
index 6bdee36a851c28e2a2e377e776ed45b384a37696..37bc54ff96c606e3048afd7a0338c826a497b491 100644 (file)
@@ -19,30 +19,18 @@ extern "C" {
 
 #define _PyRuntimeState_INIT(runtime) \
     { \
-        .gilstate = { \
-            .check_enabled = 1, \
-            /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
-               in accordance with the specification. */ \
-            .autoTSSkey = Py_tss_NEEDS_INIT, \
-        }, \
         .allocators = { \
             _pymem_allocators_standard_INIT(runtime), \
             _pymem_allocators_debug_INIT, \
             _pymem_allocators_obj_arena_INIT, \
         }, \
         .obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
+        .pyhash_state = pyhash_state_INIT, \
         .interpreters = { \
             /* This prevents interpreters from getting created \
               until _PyInterpreterState_Enable() is called. */ \
             .next_id = -1, \
         }, \
-        .tracemalloc = { \
-            .config = _PyTraceMalloc_Config_INIT, \
-        }, \
-        .dtoa = _dtoa_runtime_state_INIT(runtime), \
-        .types = { \
-            .next_version_tag = 1, \
-        }, \
         .imports = { \
             .lock = { \
                 .mutex = NULL, \
@@ -53,6 +41,26 @@ extern "C" {
                 .header = 1, \
             }, \
         }, \
+        .gilstate = { \
+            .check_enabled = 1, \
+            /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
+               in accordance with the specification. */ \
+            .autoTSSkey = Py_tss_NEEDS_INIT, \
+        }, \
+        .tracemalloc = { \
+            .config = _PyTraceMalloc_Config_INIT, \
+        }, \
+        .dtoa = _dtoa_runtime_state_INIT(runtime), \
+        .fileutils = { \
+            .force_ascii = -1, \
+        }, \
+        .float_state = { \
+            .float_format = _py_float_format_unknown, \
+            .double_format = _py_float_format_unknown, \
+        }, \
+        .types = { \
+            .next_version_tag = 1, \
+        }, \
         .global_objects = { \
             .singletons = { \
                 .small_ints = _Py_small_ints_INIT, \
index 63bf04b3e1b872c3d32e13bec0ee639f1d824c40..b315ca1ae5b64bff821cad0662d5c9b044858d09 100644 (file)
@@ -31,6 +31,10 @@ struct _Py_unicode_runtime_ids {
     Py_ssize_t next_index;
 };
 
+struct _Py_unicode_runtime_state {
+    struct _Py_unicode_runtime_ids ids;
+};
+
 /* fs_codec.encoding is initialized to NULL.
    Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
 struct _Py_unicode_fs_codec {
index aa523fc58d93fbf960fbba57a9216d5697927f47..7edfeb3365b4c691ce93a398bcd033c510f96e5b 100644 (file)
@@ -296,10 +296,10 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
         Py_DECREF(module);
         return pymain_exit_err_print();
     }
-    _Py_UnhandledKeyboardInterrupt = 0;
+    _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
     result = PyObject_Call(runmodule, runargs, NULL);
     if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
-        _Py_UnhandledKeyboardInterrupt = 1;
+        _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
     }
     Py_DECREF(runpy);
     Py_DECREF(runmodule);
@@ -696,7 +696,7 @@ Py_RunMain(void)
 
     pymain_free();
 
-    if (_Py_UnhandledKeyboardInterrupt) {
+    if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
         exitcode = exit_sigint();
     }
 
index 65383b2802c13392ba1935f35a9bd09c51d13c1e..46016e946ad344f8ce6d23993e8138c00915ee9a 100644 (file)
@@ -1723,12 +1723,14 @@ float___getnewargs___impl(PyObject *self)
 }
 
 /* this is for the benefit of the pack/unpack routines below */
+typedef enum _py_float_format_type float_format_type;
+#define unknown_format _py_float_format_unknown
+#define ieee_big_endian_format _py_float_format_ieee_big_endian
+#define ieee_little_endian_format _py_float_format_ieee_little_endian
 
-typedef enum {
-    unknown_format, ieee_big_endian_format, ieee_little_endian_format
-} float_format_type;
+#define float_format (_PyRuntime.float_state.float_format)
+#define double_format (_PyRuntime.float_state.double_format)
 
-static float_format_type double_format, float_format;
 
 /*[clinic input]
 @classmethod
@@ -1929,13 +1931,9 @@ PyTypeObject PyFloat_Type = {
     .tp_vectorcall = (vectorcallfunc)float_vectorcall,
 };
 
-void
-_PyFloat_InitState(PyInterpreterState *interp)
+static void
+_init_global_state(void)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
     float_format_type detected_double_format, detected_float_format;
 
     /* We attempt to determine if this machine is using IEEE
@@ -1985,6 +1983,15 @@ _PyFloat_InitState(PyInterpreterState *interp)
     float_format = detected_float_format;
 }
 
+void
+_PyFloat_InitState(PyInterpreterState *interp)
+{
+    if (!_Py_IsMainInterpreter(interp)) {
+        return;
+    }
+    _init_global_state();
+}
+
 PyStatus
 _PyFloat_InitTypes(PyInterpreterState *interp)
 {
index 4a423a719e90a2b40e2ee4891766d83bc90eea4d..8e03f2446f6fcd088985ba61b2b76933b84fd2b0 100644 (file)
@@ -218,6 +218,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
        _Py_PackageContext, and PyModule_Create*() will substitute this
        (if the name actually matches).
     */
+#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
     if (_Py_PackageContext != NULL) {
         const char *p = strrchr(_Py_PackageContext, '.');
         if (p != NULL && strcmp(module->m_name, p+1) == 0) {
@@ -225,6 +226,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
             _Py_PackageContext = NULL;
         }
     }
+#undef _Py_PackageContext
     if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
         return NULL;
 
index eaa8f581a75a6dd2833f2cb6a48086c3d49fd915..b1acfc71379cd55b52700f005c1e34d91ca55d68 100644 (file)
@@ -1856,7 +1856,7 @@ _PyUnicode_FromId(_Py_Identifier *id)
 
     Py_ssize_t index = _Py_atomic_size_get(&id->index);
     if (index < 0) {
-        struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_ids;
+        struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_state.ids;
 
         PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK);
         // Check again to detect concurrent access. Another thread can have
@@ -14491,12 +14491,14 @@ PyTypeObject PyUnicode_Type = {
 
 /* Initialize the Unicode implementation */
 
-void
-_PyUnicode_InitState(PyInterpreterState *interp)
+static void
+_init_global_state(void)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
+    static int initialized = 0;
+    if (initialized) {
         return;
     }
+    initialized = 1;
 
     /* initialize the linebreak bloom filter */
     const Py_UCS2 linebreak[] = {
@@ -14514,6 +14516,15 @@ _PyUnicode_InitState(PyInterpreterState *interp)
         Py_ARRAY_LENGTH(linebreak));
 }
 
+void
+_PyUnicode_InitState(PyInterpreterState *interp)
+{
+    if (!_Py_IsMainInterpreter(interp)) {
+        return;
+    }
+    _init_global_state();
+}
+
 
 PyStatus
 _PyUnicode_InitGlobalObjects(PyInterpreterState *interp)
index 3a2a7318086f777e956322469e51d6e8d4a600f5..587063ef1ab29aa4a3f667877ab32c056edfd287 100644 (file)
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include "pycore_initconfig.h"
 #include "pycore_fileutils.h"     // _Py_fstat_noraise()
+#include "pycore_runtime.h"       // _PyRuntime
 
 #ifdef MS_WINDOWS
 #  include <windows.h>
@@ -263,11 +264,7 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
 #endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
 
 
-static struct {
-    int fd;
-    dev_t st_dev;
-    ino_t st_ino;
-} urandom_cache = { -1 };
+#define urandom_cache (_PyRuntime.pyhash_state.urandom_cache)
 
 /* Read random bytes from the /dev/urandom device:
 
@@ -402,6 +399,9 @@ dev_urandom_close(void)
         urandom_cache.fd = -1;
     }
 }
+
+#undef urandom_cache
+
 #endif /* !MS_WINDOWS */
 
 
index 9b9d7dc1d1af1e7ce68281446a1442a27cdee569..83f4e91e54573a487568fd0de23eac79673dddac 100644 (file)
@@ -819,11 +819,10 @@ make_pending_calls(PyInterpreterState *interp)
     }
 
     /* don't perform recursive pending calls */
-    static int busy = 0;
-    if (busy) {
+    if (interp->ceval.pending.busy) {
         return 0;
     }
-    busy = 1;
+    interp->ceval.pending.busy = 1;
 
     /* unsignal before starting to call callbacks, so that any callback
        added in-between re-signals */
@@ -851,11 +850,11 @@ make_pending_calls(PyInterpreterState *interp)
         }
     }
 
-    busy = 0;
+    interp->ceval.pending.busy = 0;
     return res;
 
 error:
-    busy = 0;
+    interp->ceval.pending.busy = 0;
     SIGNAL_PENDING_CALLS(interp);
     return res;
 }
index fb1e5ef9a03026bb7b1e44659be5b79fb9c98104..244bd899b3bd240850ea66b10bced60c1a09de1e 100644 (file)
@@ -191,7 +191,7 @@ extern int _Py_normalize_encoding(const char *, char *, size_t);
           Py_DecodeLocale() uses mbstowcs()
       -1: unknown, need to call check_force_ascii() to get the value
 */
-static int force_ascii = -1;
+#define force_ascii (_PyRuntime.fileutils.force_ascii)
 
 static int
 check_force_ascii(void)
index 870ae2730071bb4524d314314184a364dfbbedd2..40227674ca47ee83e7ad3b57895e8235c8019c8e 100644 (file)
@@ -160,6 +160,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
     p0 = (PyModInitFunction)exportfunc;
 
     /* Package context is needed for single-phase init */
+#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
     oldcontext = _Py_PackageContext;
     _Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
     if (_Py_PackageContext == NULL) {
@@ -168,6 +169,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
     }
     m = _PyImport_InitFunc_TrampolineCall(p0);
     _Py_PackageContext = oldcontext;
+#undef _Py_PackageContext
 
     if (m == NULL) {
         if (!PyErr_Occurred()) {
index ee4bf14e63e148e9d1963abfc0367dad043f91eb..b9a10dc157e7e58d32fd02d80b255892ddeda34f 100644 (file)
@@ -10,9 +10,6 @@ typedef double va_double;
 static PyObject *va_build_value(const char *, va_list, int);
 static PyObject **va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, const char *, va_list, int, Py_ssize_t*);
 
-/* Package context -- the full module name for package imports */
-const char *_Py_PackageContext = NULL;
-
 
 int
 _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
index 7ca284ef1efb9dd8c0da069ef51a9dced993c48a..10636b4d15d73746706b61e353194b356d43cf61 100644 (file)
@@ -77,8 +77,6 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
 static void wait_for_thread_shutdown(PyThreadState *tstate);
 static void call_ll_exitfuncs(_PyRuntimeState *runtime);
 
-int _Py_UnhandledKeyboardInterrupt = 0;
-
 /* The following places the `_PyRuntime` structure in a location that can be
  * found without any external information. This is meant to ease access to the
  * interpreter state for various runtime debugging tools, but is *not* an
index 5c9e4ff85536a252d4fed7685b8f65e8169f0309..b94fbf6ca0ba0d19cb288dd3bf172ea700aa13f9 100644 (file)
@@ -137,8 +137,8 @@ init_runtime(_PyRuntimeState *runtime,
     // Set it to the ID of the main thread of the main interpreter.
     runtime->main_thread = PyThread_get_thread_ident();
 
-    runtime->unicode_ids.next_index = unicode_next_index;
-    runtime->unicode_ids.lock = unicode_ids_mutex;
+    runtime->unicode_state.ids.next_index = unicode_next_index;
+    runtime->unicode_state.ids.lock = unicode_ids_mutex;
 
     runtime->_initialized = 1;
 }
@@ -154,7 +154,7 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
     _Py_AuditHookEntry *audit_hook_head = runtime->audit_hook_head;
     // bpo-42882: Preserve next_index value if Py_Initialize()/Py_Finalize()
     // is called multiple times.
-    Py_ssize_t unicode_next_index = runtime->unicode_ids.next_index;
+    Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index;
 
     PyThread_type_lock lock1, lock2, lock3, lock4;
     if (alloc_for_runtime(&lock1, &lock2, &lock3, &lock4) != 0) {
@@ -186,7 +186,7 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
 
     FREE_LOCK(runtime->interpreters.mutex);
     FREE_LOCK(runtime->xidregistry.mutex);
-    FREE_LOCK(runtime->unicode_ids.lock);
+    FREE_LOCK(runtime->unicode_state.ids.lock);
     FREE_LOCK(runtime->getargs.mutex);
 
 #undef FREE_LOCK
@@ -209,7 +209,7 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
 
     int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
     int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
-    int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_ids.lock);
+    int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_state.ids.lock);
     int reinit_getargs = _PyThread_at_fork_reinit(&runtime->getargs.mutex);
 
     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
index 1c7ac4af63c6be5f893c35f7889bb950e605ea8a..eead707b541084f0ab651c2ba25830cd2067c1c7 100644 (file)
@@ -1688,7 +1688,8 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
      * uncaught exception to trigger an unexplained signal exit from a future
      * Py_Main() based one.
      */
-    _Py_UnhandledKeyboardInterrupt = 0;
+    // XXX Isn't this dealt with by the move to _PyRuntimeState?
+    _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
 
     /* Set globals['__builtins__'] if it doesn't exist */
     if (globals != NULL && _PyDict_GetItemStringWithError(globals, "__builtins__") == NULL) {
@@ -1702,7 +1703,7 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
 
     v = PyEval_EvalCode((PyObject*)co, globals, locals);
     if (!v && _PyErr_Occurred(tstate) == PyExc_KeyboardInterrupt) {
-        _Py_UnhandledKeyboardInterrupt = 1;
+        _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
     }
     return v;
 }
index b4ac9120d98bb075826a417fa30dc9defbeb40e2..ee0c85bd425e8744a09a0c8bf2f71d74d40c4275 100644 (file)
@@ -336,17 +336,7 @@ Python/perf_trampoline.c   -       perf_status     -
 Python/perf_trampoline.c       -       extra_code_index        -
 Python/perf_trampoline.c       -       code_arena      -
 Python/perf_trampoline.c       -       trampoline_api  -
-Parser/pegen.c -       memo_statistics -
-Python/bootstrap_hash.c        -       urandom_cache   -
-Python/ceval_gil.c     make_pending_calls      busy    -
-Python/ceval.c _PyEval_SetProfile      reentrant       -
-Python/ceval.c _PyEval_SetTrace        reentrant       -
-Python/modsupport.c    -       _Py_PackageContext      -
 Python/thread_pthread_stubs.h  -       py_tls_entries  -
-Python/pyfpe.c -       PyFPE_counter   -
-Python/pylifecycle.c   _Py_FatalErrorFormat    reentrant       -
-Python/pylifecycle.c   -       _Py_UnhandledKeyboardInterrupt  -
-Python/pylifecycle.c   fatal_error     reentrant       -
 
 
 ##################################
index 0a6f3ec8152dd3c6c804f4a7c87019ed3cac5a3b..242deace8c945deafc119c4a8925e89c1456cb89 100644 (file)
@@ -1,16 +1,95 @@
 filename       funcname        name    reason
 #???   -       somevar ???
 
+# All globals here are technically mutable but known to be safe.
+
+
+##################################
+# process-global resources
+
+# Initialization for these should be idempotent.
+
+#-----------------------
+# effectively const, set once before/during first init
+
+Modules/getbuildinfo.c -       buildinfo       -
+Modules/getbuildinfo.c -       initialized     -
+Python/getversion.c    -       initialized     -
+Python/getversion.c    -       version -
+
+#-----------------------
+# effectively const, set once during first init
+
+Python/bootstrap_hash.c        -       _Py_HashSecret_Initialized      -
+Python/pyhash.c        -       _Py_HashSecret  -
+Python/thread.c        -       initialized     -
+Python/thread_pthread.h        -       condattr_monotonic      -
+
+# safe static buffer used during one-time initialization
+Python/thread_pthread.h        init_condattr   ca      -
+
+# indicators for process-global resource availability/capability
+Python/bootstrap_hash.c        py_getrandom    getrandom_works -
+Python/fileutils.c     -       _Py_open_cloexec_works  -
+Python/fileutils.c     set_inheritable ioctl_works     -
+
+#-----------------------
+# effectively const but set once lazily (*after* first init)
+
+Objects/longobject.c   long_from_non_binary_base       log_base_BASE   -
+Objects/longobject.c   long_from_non_binary_base       convwidth_base  -
+Objects/longobject.c   long_from_non_binary_base       convmultmax_base        -
+Objects/unicodeobject.c        -       bloom_linebreak -
+Objects/unicodeobject.c        _init_global_state      initialized     -
+
+# XXX Move to _PyRuntimeState?
+Parser/action_helpers.c        _PyPegen_dummy_name     cache   -
+
+
 ##################################
-# mutable but known to be safe
+# state tied to C main() (only in main thread)
+
+#-----------------------
+# handling C argv
+
+Python/getopt.c        -       _PyOS_optarg    -
+Python/getopt.c        -       _PyOS_opterr    -
+Python/getopt.c        -       _PyOS_optind    -
+Python/getopt.c        -       opt_ptr -
+Python/pathconfig.c    -       _Py_path_config -
+
+#-----------------------
+# REPL
+
+Parser/myreadline.c    -       _PyOS_ReadlineLock      -
+Parser/myreadline.c    -       _PyOS_ReadlineTState    -
+Parser/myreadline.c    -       PyOS_InputHook  -
+Parser/myreadline.c    -       PyOS_ReadlineFunctionPointer    -
+
+
+##################################
+# state tied to each runtime init/fini cycle
 
 Python/pylifecycle.c   -       _PyRuntime      -
+Python/pylifecycle.c   -       runtime_initialized     -
 
 # All uses of _PyArg_Parser are handled in c-analyzr/cpython/_analyzer.py.
 
 #-----------------------
-# legacy config flags
+# effectively const once init finishes
+
+# set by embedders before init (whether directly or through a call)
+Python/initconfig.c    -       _Py_StandardStreamEncoding      -
+Python/initconfig.c    -       _Py_StandardStreamErrors        -
+Python/initconfig.c    -       orig_argv       -
+
+# deprecated
+Python/preconfig.c     -       Py_FileSystemDefaultEncoding    -
+Python/preconfig.c     -       Py_HasFileSystemDefaultEncoding -
+Python/preconfig.c     -       Py_FileSystemDefaultEncodeErrors        -
+Python/preconfig.c     -       _Py_HasFileSystemDefaultEncodeErrors    -
 
+# legacy config flags
 Python/initconfig.c    -       Py_UTF8Mode     -
 Python/initconfig.c    -       Py_DebugFlag    -
 Python/initconfig.c    -       Py_VerboseFlag  -
@@ -30,75 +109,34 @@ Python/initconfig.c        -       Py_IsolatedFlag -
 Python/initconfig.c    -       Py_LegacyWindowsFSEncodingFlag  -
 Python/initconfig.c    -       Py_LegacyWindowsStdioFlag       -
 
-#-----------------------
-# effectively const, initialized before init
-
+# initialized statically, customized by embedders
 Python/frozen.c        -       PyImport_FrozenModules  -
 Python/import.c        -       inittab_copy    -
 Python/import.c        -       PyImport_Inittab        -
 
-#-----------------------
-# effectively const, initialized before/during init
+# used temporarily during init
+Python/sysmodule.c     -       _preinit_warnoptions    -
+Python/sysmodule.c     -       _preinit_xoptions       -
 
-Modules/getbuildinfo.c -       buildinfo       -
-Modules/getbuildinfo.c -       initialized     -
-Python/getversion.c    -       initialized     -
-Python/getversion.c    -       version -
 
-#-----------------------
-# effectively const, initialized during init
+##################################
+# special-use diagnistic state
 
-Objects/floatobject.c  -       double_format   -
-Objects/floatobject.c  -       float_format    -
-Objects/unicodeobject.c        -       bloom_linebreak -
-Python/bootstrap_hash.c        py_getrandom    getrandom_works -
-Python/bootstrap_hash.c        -       _Py_HashSecret_Initialized      -
-Python/fileutils.c     -       _Py_open_cloexec_works  -
-Python/fileutils.c     -       force_ascii     -
-Python/fileutils.c     set_inheritable ioctl_works     -
-Python/import.c        import_find_and_load    header  -
-Python/initconfig.c    -       orig_argv       -
-Python/preconfig.c     -       Py_FileSystemDefaultEncoding    -
-Python/preconfig.c     -       Py_HasFileSystemDefaultEncoding -
-Python/preconfig.c     -       Py_FileSystemDefaultEncodeErrors        -
-Python/preconfig.c     -       _Py_HasFileSystemDefaultEncodeErrors    -
-Python/pyhash.c        -       _Py_HashSecret  -
-Python/pylifecycle.c   -       runtime_initialized     -
-Python/sysmodule.c     -       _preinit_warnoptions    -
-Python/sysmodule.c     -       _preinit_xoptions       -
-Python/thread.c        -       initialized     -
-Python/thread_pthread.h        -       condattr_monotonic      -
-Python/thread_pthread.h        init_condattr   ca      -
+Parser/pegen.c -       memo_statistics -
 
-# set by embedders during init
-Python/initconfig.c    -       _Py_StandardStreamEncoding      -
-Python/initconfig.c    -       _Py_StandardStreamErrors        -
 
-#-----------------------
-# effectively const but initialized lazily
-# XXX Move them to _PyRuntimeState?
+##################################
+# one-off temporary state
 
-# idempotent
-Objects/longobject.c   long_from_non_binary_base       log_base_BASE   -
-Objects/longobject.c   long_from_non_binary_base       convwidth_base  -
-Objects/longobject.c   long_from_non_binary_base       convmultmax_base        -
-Parser/action_helpers.c        _PyPegen_dummy_name     cache   -
+# This is safe enough.
+Python/pylifecycle.c   _Py_FatalErrorFormat    reentrant       -
+Python/pylifecycle.c   fatal_error     reentrant       -
 
-#-----------------------
-# used only in the main thread
 
-# REPL
-Parser/myreadline.c    -       _PyOS_ReadlineLock      -
-Parser/myreadline.c    -       _PyOS_ReadlineTState    -
-Parser/myreadline.c    -       PyOS_InputHook  -
-Parser/myreadline.c    -       PyOS_ReadlineFunctionPointer    -
+##################################
+# not used (kept for compatibility)
 
-# handling C argv
-Python/getopt.c        -       _PyOS_optarg    -
-Python/getopt.c        -       _PyOS_opterr    -
-Python/getopt.c        -       _PyOS_optind    -
-Python/getopt.c        -       opt_ptr -
-Python/pathconfig.c    -       _Py_path_config -
+Python/pyfpe.c -       PyFPE_counter   -
 
 
 ##################################