#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 */