mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			206 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef Py_INTERNAL_PYSTATE_H
 | |
| #define Py_INTERNAL_PYSTATE_H
 | |
| #ifdef __cplusplus
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| #include "pystate.h"
 | |
| #include "pyatomic.h"
 | |
| #include "pythread.h"
 | |
| 
 | |
| #include "internal/mem.h"
 | |
| #include "internal/ceval.h"
 | |
| #include "internal/warnings.h"
 | |
| 
 | |
| 
 | |
| /* 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;
 | |
|     PyThreadFrameGetter getframe;
 | |
|     /* 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;
 | |
| };
 | |
| 
 | |
| /* hook for PyEval_GetFrame(), requested for Psyco */
 | |
| #define _PyThreadState_GetFrame _PyRuntime.gilstate.getframe
 | |
| 
 | |
| /* 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
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
|     /* Full path to the Python program */
 | |
|     wchar_t *program_full_path;
 | |
|     wchar_t *prefix;
 | |
| #ifdef MS_WINDOWS
 | |
|     wchar_t *dll_path;
 | |
| #else
 | |
|     wchar_t *exec_prefix;
 | |
| #endif
 | |
|     /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
 | |
|     wchar_t *module_search_path;
 | |
|     /* Python program name */
 | |
|     wchar_t *program_name;
 | |
|     /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */
 | |
|     wchar_t *home;
 | |
| } _PyPathConfig;
 | |
| 
 | |
| #define _PyPathConfig_INIT {.module_search_path = NULL}
 | |
| /* Note: _PyPathConfig_INIT sets other fields to 0/NULL */
 | |
| 
 | |
| PyAPI_DATA(_PyPathConfig) _Py_path_config;
 | |
| 
 | |
| PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate(
 | |
|     _PyPathConfig *config,
 | |
|     const _PyCoreConfig *core_config);
 | |
| PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config);
 | |
| 
 | |
| 
 | |
| /* interpreter state */
 | |
| 
 | |
| PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(PY_INT64_T);
 | |
| 
 | |
| PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *);
 | |
| PyAPI_FUNC(void) _PyInterpreterState_IDIncref(PyInterpreterState *);
 | |
| PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *);
 | |
| 
 | |
| 
 | |
| /* cross-interpreter data */
 | |
| 
 | |
| struct _xid;
 | |
| 
 | |
| // _PyCrossInterpreterData is similar to Py_buffer as an effectively
 | |
| // opaque struct that holds data outside the object machinery.  This
 | |
| // is necessary to pass between interpreters in the same process.
 | |
| typedef struct _xid {
 | |
|     // data is the cross-interpreter-safe derivation of a Python object
 | |
|     // (see _PyObject_GetCrossInterpreterData).  It will be NULL if the
 | |
|     // new_object func (below) encodes the data.
 | |
|     void *data;
 | |
|     // obj is the Python object from which the data was derived.  This
 | |
|     // is non-NULL only if the data remains bound to the object in some
 | |
|     // way, such that the object must be "released" (via a decref) when
 | |
|     // the data is released.  In that case it is automatically
 | |
|     // incref'ed (to match the automatic decref when releaed).
 | |
|     PyObject *obj;
 | |
|     // interp is the ID of the owning interpreter of the original
 | |
|     // object.  It corresponds to the active interpreter when
 | |
|     // _PyObject_GetCrossInterpreterData() was called.  This should only
 | |
|     // be set by the cross-interpreter machinery.
 | |
|     //
 | |
|     // We use the ID rather than the PyInterpreterState to avoid issues
 | |
|     // with deleted interpreters.
 | |
|     int64_t interp;
 | |
|     // new_object is a function that returns a new object in the current
 | |
|     // interpreter given the data.  The resulting object (a new
 | |
|     // reference) will be equivalent to the original object.  This field
 | |
|     // is required.
 | |
|     PyObject *(*new_object)(struct _xid *);
 | |
|     // free is called when the data is released.  If it is NULL then
 | |
|     // nothing will be done to free the data.  For some types this is
 | |
|     // okay (e.g. bytes) and for those types this field should be set
 | |
|     // to NULL.  However, for most the data was allocated just for
 | |
|     // cross-interpreter use, so it must be freed when
 | |
|     // _PyCrossInterpreterData_Release is called or the memory will
 | |
|     // leak.  In that case, at the very least this field should be set
 | |
|     // to PyMem_RawFree (the default if not explicitly set to NULL).
 | |
|     // The call will happen with the original interpreter activated.
 | |
|     void (*free)(void *);
 | |
| } _PyCrossInterpreterData;
 | |
| 
 | |
| typedef int (*crossinterpdatafunc)(PyObject *, _PyCrossInterpreterData *);
 | |
| PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);
 | |
| 
 | |
| PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *);
 | |
| PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *);
 | |
| PyAPI_FUNC(void) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);
 | |
| 
 | |
| /* cross-interpreter data registry */
 | |
| 
 | |
| /* For now we use a global registry of shareable classes.  An
 | |
|    alternative would be to add a tp_* slot for a class's
 | |
|    crossinterpdatafunc. It would be simpler and more efficient. */
 | |
| 
 | |
| PyAPI_FUNC(int) _PyCrossInterpreterData_Register_Class(PyTypeObject *, crossinterpdatafunc);
 | |
| PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
 | |
| 
 | |
| struct _xidregitem;
 | |
| 
 | |
| struct _xidregitem {
 | |
|     PyTypeObject *cls;
 | |
|     crossinterpdatafunc getdata;
 | |
|     struct _xidregitem *next;
 | |
| };
 | |
| 
 | |
| 
 | |
| /* Full Python runtime state */
 | |
| 
 | |
| typedef struct pyruntimestate {
 | |
|     int initialized;
 | |
|     int core_initialized;
 | |
|     PyThreadState *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;
 | |
| 
 | |
| #define NEXITFUNCS 32
 | |
|     void (*exitfuncs[NEXITFUNCS])(void);
 | |
|     int nexitfuncs;
 | |
| 
 | |
|     struct _gc_runtime_state gc;
 | |
|     struct _warnings_runtime_state warnings;
 | |
|     struct _ceval_runtime_state ceval;
 | |
|     struct _gilstate_runtime_state gilstate;
 | |
| 
 | |
|     // XXX Consolidate globals found via the check-c-globals script.
 | |
| } _PyRuntimeState;
 | |
| 
 | |
| #define _PyRuntimeState_INIT {.initialized = 0, .core_initialized = 0}
 | |
| /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
 | |
| 
 | |
| PyAPI_DATA(_PyRuntimeState) _PyRuntime;
 | |
| PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *);
 | |
| PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *);
 | |
| 
 | |
| /* Initialize _PyRuntimeState.
 | |
|    Return NULL on success, or return an error message on failure. */
 | |
| PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);
 | |
| 
 | |
| #define _Py_CURRENTLY_FINALIZING(tstate) \
 | |
|     (_PyRuntime.finalizing == tstate)
 | |
| 
 | |
| 
 | |
| /* Other */
 | |
| 
 | |
| PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| }
 | |
| #endif
 | |
| #endif /* !Py_INTERNAL_PYSTATE_H */
 | 
