mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-40268: Add pycore_runtime.h header file (GH-19493)
Move PyRuntimeState from pycore_pystate.h to pycore_runtime.h. Remove _PyGILState_check_enabled macro: access directly _PyRuntime.gilstate.check_enabled.
This commit is contained in:
		
							parent
							
								
									0135598d72
								
							
						
					
					
						commit
						1c4cbdf94d
					
				
					 7 changed files with 152 additions and 125 deletions
				
			
		|  | @ -11,6 +11,7 @@ extern "C" { | |||
| #include "pycore_gil.h"       /* struct _gil_runtime_state  */ | ||||
| #include "pycore_pymem.h"     /* struct _gc_runtime_state */ | ||||
| #include "pycore_warnings.h"  /* struct _warnings_runtime_state */ | ||||
| #include "pycore_runtime.h"   /* PyRuntimestate */ | ||||
| 
 | ||||
| 
 | ||||
| /* ceval state */ | ||||
|  | @ -32,15 +33,6 @@ struct _pending_calls { | |||
|     int last; | ||||
| }; | ||||
| 
 | ||||
| struct _ceval_runtime_state { | ||||
|     int recursion_limit; | ||||
|     /* Request for dropping the GIL */ | ||||
|     _Py_atomic_int gil_drop_request; | ||||
|     /* Request for checking signals. */ | ||||
|     _Py_atomic_int signals_pending; | ||||
|     struct _gil_runtime_state gil; | ||||
| }; | ||||
| 
 | ||||
| struct _ceval_state { | ||||
|     /* Records whether tracing is on for any thread.  Counts the number
 | ||||
|        of threads for which tstate->c_tracefunc is non-NULL, so if the | ||||
|  | @ -176,118 +168,6 @@ struct _xidregitem { | |||
|     struct _xidregitem *next; | ||||
| }; | ||||
| 
 | ||||
| /* runtime audit hook state */ | ||||
| 
 | ||||
| typedef struct _Py_AuditHookEntry { | ||||
|     struct _Py_AuditHookEntry *next; | ||||
|     Py_AuditHookFunction hookCFunction; | ||||
|     void *userData; | ||||
| } _Py_AuditHookEntry; | ||||
| 
 | ||||
| /* GIL state */ | ||||
| 
 | ||||
| struct _gilstate_runtime_state { | ||||
|     int check_enabled; | ||||
|     /* Assuming the current thread holds the GIL, this is the
 | ||||
|        PyThreadState for the current thread. */ | ||||
|     _Py_atomic_address tstate_current; | ||||
|     /* The single PyInterpreterState used by this process'
 | ||||
|        GILState implementation | ||||
|     */ | ||||
|     /* TODO: Given interp_main, it may be possible to kill this ref */ | ||||
|     PyInterpreterState *autoInterpreterState; | ||||
|     Py_tss_t autoTSSkey; | ||||
| }; | ||||
| 
 | ||||
| /* Issue #26558: Flag to disable PyGILState_Check().
 | ||||
|    If set to non-zero, PyGILState_Check() always return 1. */ | ||||
| #define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled | ||||
| 
 | ||||
| 
 | ||||
| /* Full Python runtime state */ | ||||
| 
 | ||||
| typedef struct pyruntimestate { | ||||
|     /* Is running Py_PreInitialize()? */ | ||||
|     int preinitializing; | ||||
| 
 | ||||
|     /* Is Python preinitialized? Set to 1 by Py_PreInitialize() */ | ||||
|     int preinitialized; | ||||
| 
 | ||||
|     /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ | ||||
|     int core_initialized; | ||||
| 
 | ||||
|     /* Is Python fully initialized? Set to 1 by Py_Initialize() */ | ||||
|     int initialized; | ||||
| 
 | ||||
|     /* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize()
 | ||||
|        is called again. | ||||
| 
 | ||||
|        Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing() | ||||
|        to access it, don't access it directly. */ | ||||
|     _Py_atomic_address _finalizing; | ||||
| 
 | ||||
|     struct pyinterpreters { | ||||
|         PyThread_type_lock mutex; | ||||
|         PyInterpreterState *head; | ||||
|         PyInterpreterState *main; | ||||
|         /* _next_interp_id is an auto-numbered sequence of small
 | ||||
|            integers.  It gets initialized in _PyInterpreterState_Init(), | ||||
|            which is called in Py_Initialize(), and used in | ||||
|            PyInterpreterState_New().  A negative interpreter ID | ||||
|            indicates an error occurred.  The main interpreter will | ||||
|            always have an ID of 0.  Overflow results in a RuntimeError. | ||||
|            If that becomes a problem later then we can adjust, e.g. by | ||||
|            using a Python int. */ | ||||
|         int64_t next_id; | ||||
|     } interpreters; | ||||
|     // XXX Remove this field once we have a tp_* slot.
 | ||||
|     struct _xidregistry { | ||||
|         PyThread_type_lock mutex; | ||||
|         struct _xidregitem *head; | ||||
|     } xidregistry; | ||||
| 
 | ||||
|     unsigned long main_thread; | ||||
| 
 | ||||
| #define NEXITFUNCS 32 | ||||
|     void (*exitfuncs[NEXITFUNCS])(void); | ||||
|     int nexitfuncs; | ||||
| 
 | ||||
|     struct _ceval_runtime_state ceval; | ||||
|     struct _gilstate_runtime_state gilstate; | ||||
| 
 | ||||
|     PyPreConfig preconfig; | ||||
| 
 | ||||
|     Py_OpenCodeHookFunction open_code_hook; | ||||
|     void *open_code_userdata; | ||||
|     _Py_AuditHookEntry *audit_hook_head; | ||||
| 
 | ||||
|     // XXX Consolidate globals found via the check-c-globals script.
 | ||||
| } _PyRuntimeState; | ||||
| 
 | ||||
| #define _PyRuntimeState_INIT \ | ||||
|     {.preinitialized = 0, .core_initialized = 0, .initialized = 0} | ||||
| /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ | ||||
| 
 | ||||
| PyAPI_DATA(_PyRuntimeState) _PyRuntime; | ||||
| PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime); | ||||
| PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); | ||||
| PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); | ||||
| 
 | ||||
| /* Initialize _PyRuntimeState.
 | ||||
|    Return NULL on success, or return an error message on failure. */ | ||||
| PyAPI_FUNC(PyStatus) _PyRuntime_Initialize(void); | ||||
| 
 | ||||
| PyAPI_FUNC(void) _PyRuntime_Finalize(void); | ||||
| 
 | ||||
| static inline PyThreadState* | ||||
| _PyRuntimeState_GetFinalizing(_PyRuntimeState *runtime) { | ||||
|     return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->_finalizing); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| _PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { | ||||
|     _Py_atomic_store_relaxed(&runtime->_finalizing, (uintptr_t)tstate); | ||||
| } | ||||
| 
 | ||||
| /* Check if the current thread is the main thread.
 | ||||
|    Use _Py_IsMainInterpreter() to check if it's the main interpreter. */ | ||||
|  |  | |||
							
								
								
									
										143
									
								
								Include/internal/pycore_runtime.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								Include/internal/pycore_runtime.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| #ifndef Py_INTERNAL_RUNTIME_H | ||||
| #define Py_INTERNAL_RUNTIME_H | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #ifndef Py_BUILD_CORE | ||||
| #  error "this header requires Py_BUILD_CORE define" | ||||
| #endif | ||||
| 
 | ||||
| #include "pycore_atomic.h"    /* _Py_atomic_address */ | ||||
| #include "pycore_gil.h"       // struct _gil_runtime_state | ||||
| 
 | ||||
| /* ceval state */ | ||||
| 
 | ||||
| struct _ceval_runtime_state { | ||||
|     int recursion_limit; | ||||
|     /* Request for dropping the GIL */ | ||||
|     _Py_atomic_int gil_drop_request; | ||||
|     /* Request for checking signals. */ | ||||
|     _Py_atomic_int signals_pending; | ||||
|     struct _gil_runtime_state gil; | ||||
| }; | ||||
| 
 | ||||
| /* GIL state */ | ||||
| 
 | ||||
| struct _gilstate_runtime_state { | ||||
|     /* bpo-26558: Flag to disable PyGILState_Check().
 | ||||
|        If set to non-zero, PyGILState_Check() always return 1. */ | ||||
|     int check_enabled; | ||||
|     /* Assuming the current thread holds the GIL, this is the
 | ||||
|        PyThreadState for the current thread. */ | ||||
|     _Py_atomic_address tstate_current; | ||||
|     /* The single PyInterpreterState used by this process'
 | ||||
|        GILState implementation | ||||
|     */ | ||||
|     /* TODO: Given interp_main, it may be possible to kill this ref */ | ||||
|     PyInterpreterState *autoInterpreterState; | ||||
|     Py_tss_t autoTSSkey; | ||||
| }; | ||||
| 
 | ||||
| /* Runtime audit hook state */ | ||||
| 
 | ||||
| typedef struct _Py_AuditHookEntry { | ||||
|     struct _Py_AuditHookEntry *next; | ||||
|     Py_AuditHookFunction hookCFunction; | ||||
|     void *userData; | ||||
| } _Py_AuditHookEntry; | ||||
| 
 | ||||
| /* Full Python runtime state */ | ||||
| 
 | ||||
| typedef struct pyruntimestate { | ||||
|     /* Is running Py_PreInitialize()? */ | ||||
|     int preinitializing; | ||||
| 
 | ||||
|     /* Is Python preinitialized? Set to 1 by Py_PreInitialize() */ | ||||
|     int preinitialized; | ||||
| 
 | ||||
|     /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ | ||||
|     int core_initialized; | ||||
| 
 | ||||
|     /* Is Python fully initialized? Set to 1 by Py_Initialize() */ | ||||
|     int initialized; | ||||
| 
 | ||||
|     /* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize()
 | ||||
|        is called again. | ||||
| 
 | ||||
|        Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing() | ||||
|        to access it, don't access it directly. */ | ||||
|     _Py_atomic_address _finalizing; | ||||
| 
 | ||||
|     struct pyinterpreters { | ||||
|         PyThread_type_lock mutex; | ||||
|         PyInterpreterState *head; | ||||
|         PyInterpreterState *main; | ||||
|         /* _next_interp_id is an auto-numbered sequence of small
 | ||||
|            integers.  It gets initialized in _PyInterpreterState_Init(), | ||||
|            which is called in Py_Initialize(), and used in | ||||
|            PyInterpreterState_New().  A negative interpreter ID | ||||
|            indicates an error occurred.  The main interpreter will | ||||
|            always have an ID of 0.  Overflow results in a RuntimeError. | ||||
|            If that becomes a problem later then we can adjust, e.g. by | ||||
|            using a Python int. */ | ||||
|         int64_t next_id; | ||||
|     } interpreters; | ||||
|     // XXX Remove this field once we have a tp_* slot.
 | ||||
|     struct _xidregistry { | ||||
|         PyThread_type_lock mutex; | ||||
|         struct _xidregitem *head; | ||||
|     } xidregistry; | ||||
| 
 | ||||
|     unsigned long main_thread; | ||||
| 
 | ||||
| #define NEXITFUNCS 32 | ||||
|     void (*exitfuncs[NEXITFUNCS])(void); | ||||
|     int nexitfuncs; | ||||
| 
 | ||||
|     struct _ceval_runtime_state ceval; | ||||
|     struct _gilstate_runtime_state gilstate; | ||||
| 
 | ||||
|     PyPreConfig preconfig; | ||||
| 
 | ||||
|     Py_OpenCodeHookFunction open_code_hook; | ||||
|     void *open_code_userdata; | ||||
|     _Py_AuditHookEntry *audit_hook_head; | ||||
| 
 | ||||
|     // XXX Consolidate globals found via the check-c-globals script.
 | ||||
| } _PyRuntimeState; | ||||
| 
 | ||||
| #define _PyRuntimeState_INIT \ | ||||
|     {.preinitialized = 0, .core_initialized = 0, .initialized = 0} | ||||
| /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ | ||||
| 
 | ||||
| 
 | ||||
| PyAPI_DATA(_PyRuntimeState) _PyRuntime; | ||||
| 
 | ||||
| PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime); | ||||
| PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); | ||||
| 
 | ||||
| PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); | ||||
| 
 | ||||
| 
 | ||||
| /* Initialize _PyRuntimeState.
 | ||||
|    Return NULL on success, or return an error message on failure. */ | ||||
| PyAPI_FUNC(PyStatus) _PyRuntime_Initialize(void); | ||||
| 
 | ||||
| PyAPI_FUNC(void) _PyRuntime_Finalize(void); | ||||
| 
 | ||||
| 
 | ||||
| static inline PyThreadState* | ||||
| _PyRuntimeState_GetFinalizing(_PyRuntimeState *runtime) { | ||||
|     return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->_finalizing); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| _PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { | ||||
|     _Py_atomic_store_relaxed(&runtime->_finalizing, (uintptr_t)tstate); | ||||
| } | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif /* !Py_INTERNAL_RUNTIME_H */ | ||||
|  | @ -1103,6 +1103,7 @@ PYTHON_HEADERS= \ | |||
| 		$(srcdir)/Include/internal/pycore_pylifecycle.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_pymem.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_pystate.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_runtime.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_sysmodule.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_traceback.h \ | ||||
| 		$(srcdir)/Include/internal/pycore_tupleobject.h \ | ||||
|  |  | |||
|  | @ -184,6 +184,7 @@ | |||
|     <ClInclude Include="..\Include\internal\pycore_pylifecycle.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_pymem.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_pystate.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_runtime.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_sysmodule.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_traceback.h" /> | ||||
|     <ClInclude Include="..\Include\internal\pycore_tupleobject.h" /> | ||||
|  |  | |||
|  | @ -255,6 +255,9 @@ | |||
|     <ClInclude Include="..\Include\internal\pycore_pystate.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Include\internal\pycore_runtime.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Include\internal\pycore_sysmodule.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|  |  | |||
|  | @ -1553,7 +1553,7 @@ new_interpreter(PyThreadState **tstate_p) | |||
| 
 | ||||
|     /* Issue #10915, #15751: The GIL API doesn't work with multiple
 | ||||
|        interpreters: disable PyGILState_Check(). */ | ||||
|     _PyGILState_check_enabled = 0; | ||||
|     runtime->gilstate.check_enabled = 0; | ||||
| 
 | ||||
|     PyInterpreterState *interp = PyInterpreterState_New(); | ||||
|     if (interp == NULL) { | ||||
|  |  | |||
|  | @ -1329,12 +1329,11 @@ PyGILState_GetThisThreadState(void) | |||
| int | ||||
| PyGILState_Check(void) | ||||
| { | ||||
| 
 | ||||
|     if (!_PyGILState_check_enabled) { | ||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||
|     if (!gilstate->check_enabled) { | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||
|     if (!PyThread_tss_is_created(&gilstate->autoTSSkey)) { | ||||
|         return 1; | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner