| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- #ifndef Py_INTERNAL_PYSTATE_H
- #define Py_INTERNAL_PYSTATE_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifndef Py_BUILD_CORE
- # error "this header requires Py_BUILD_CORE define"
- #endif
- #include "cpython/initconfig.h"
- #include "fileobject.h"
- #include "pystate.h"
- #include "pythread.h"
- #include "sysmodule.h"
- #include "pycore_gil.h" /* _gil_runtime_state */
- #include "pycore_pathconfig.h"
- #include "pycore_pymem.h"
- #include "pycore_warnings.h"
- /* ceval state */
- struct _pending_calls {
- int finishing;
- PyThread_type_lock lock;
- /* Request for running pending calls. */
- _Py_atomic_int calls_to_do;
- /* Request for looking at the `async_exc` field of the current
- thread state.
- Guarded by the GIL. */
- int async_exc;
- #define NPENDINGCALLS 32
- struct {
- int (*func)(void *);
- void *arg;
- } calls[NPENDINGCALLS];
- int first;
- int last;
- };
- struct _ceval_runtime_state {
- int recursion_limit;
- /* Records whether tracing is on for any thread. Counts the number
- of threads for which tstate->c_tracefunc is non-NULL, so if the
- value is 0, we know we don't have to check this thread's
- c_tracefunc. This speeds up the if statement in
- PyEval_EvalFrameEx() after fast_next_opcode. */
- int tracing_possible;
- /* This single variable consolidates all requests to break out of
- the fast path in the eval loop. */
- _Py_atomic_int eval_breaker;
- /* Request for dropping the GIL */
- _Py_atomic_int gil_drop_request;
- struct _pending_calls pending;
- /* Request for checking signals. */
- _Py_atomic_int signals_pending;
- struct _gil_runtime_state gil;
- };
- /* interpreter state */
- typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
- // The PyInterpreterState typedef is in Include/pystate.h.
- struct _is {
- struct _is *next;
- struct _ts *tstate_head;
- int64_t id;
- int64_t id_refcount;
- int requires_idref;
- PyThread_type_lock id_mutex;
- int finalizing;
- PyObject *modules;
- PyObject *modules_by_index;
- PyObject *sysdict;
- PyObject *builtins;
- PyObject *importlib;
- /* Used in Python/sysmodule.c. */
- int check_interval;
- /* Used in Modules/_threadmodule.c. */
- long num_threads;
- /* Support for runtime thread stack size tuning.
- A value of 0 means using the platform's default stack size
- or the size specified by the THREAD_STACK_SIZE macro. */
- /* Used in Python/thread.c. */
- size_t pythread_stacksize;
- PyObject *codec_search_path;
- PyObject *codec_search_cache;
- PyObject *codec_error_registry;
- int codecs_initialized;
- /* fs_codec.encoding is initialized to NULL.
- Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
- struct {
- char *encoding; /* Filesystem encoding (encoded to UTF-8) */
- char *errors; /* Filesystem errors (encoded to UTF-8) */
- _Py_error_handler error_handler;
- } fs_codec;
- PyConfig config;
- #ifdef HAVE_DLOPEN
- int dlopenflags;
- #endif
- PyObject *dict; /* Stores per-interpreter state */
- PyObject *builtins_copy;
- PyObject *import_func;
- /* Initialized to PyEval_EvalFrameDefault(). */
- _PyFrameEvalFunction eval_frame;
- Py_ssize_t co_extra_user_count;
- freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];
- #ifdef HAVE_FORK
- PyObject *before_forkers;
- PyObject *after_forkers_parent;
- PyObject *after_forkers_child;
- #endif
- /* AtExit module */
- void (*pyexitfunc)(PyObject *);
- PyObject *pyexitmodule;
- uint64_t tstate_next_unique_id;
- struct _warnings_runtime_state warnings;
- PyObject *audit_hooks;
- };
- PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_INT64_T);
- PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *);
- PyAPI_FUNC(void) _PyInterpreterState_IDIncref(struct _is *);
- PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *);
- /* 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. */
- struct _xidregitem;
- struct _xidregitem {
- PyTypeObject *cls;
- crossinterpdatafunc getdata;
- 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;
- 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
- /* 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. */
- 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;
- unsigned long main_thread;
- #define NEXITFUNCS 32
- void (*exitfuncs[NEXITFUNCS])(void);
- int nexitfuncs;
- struct _gc_runtime_state gc;
- 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);
- #define _Py_CURRENTLY_FINALIZING(runtime, tstate) \
- (runtime->finalizing == tstate)
- /* Variable and macro for in-line access to current thread
- and interpreter state */
- #define _PyRuntimeState_GetThreadState(runtime) \
- ((PyThreadState*)_Py_atomic_load_relaxed(&(runtime)->gilstate.tstate_current))
- /* Get the current Python thread state.
- Efficient macro reading directly the 'gilstate.tstate_current' atomic
- variable. The macro is unsafe: it does not check for error and it can
- return NULL.
- The caller must hold the GIL.
- See also PyThreadState_Get() and PyThreadState_GET(). */
- #define _PyThreadState_GET() _PyRuntimeState_GetThreadState(&_PyRuntime)
- /* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
- #undef PyThreadState_GET
- #define PyThreadState_GET() _PyThreadState_GET()
- /* Get the current interpreter state.
- The macro is unsafe: it does not check for error and it can return NULL.
- The caller must hold the GIL.
- See also _PyInterpreterState_Get()
- and _PyGILState_GetInterpreterStateUnsafe(). */
- #define _PyInterpreterState_GET_UNSAFE() (_PyThreadState_GET()->interp)
- /* Other */
- PyAPI_FUNC(void) _PyThreadState_Init(
- _PyRuntimeState *runtime,
- PyThreadState *tstate);
- PyAPI_FUNC(void) _PyThreadState_DeleteExcept(
- _PyRuntimeState *runtime,
- PyThreadState *tstate);
- PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
- struct _gilstate_runtime_state *gilstate,
- PyThreadState *newts);
- PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
- PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
- PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
- #ifdef __cplusplus
- }
- #endif
- #endif /* !Py_INTERNAL_PYSTATE_H */
|