diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-11-26 23:20:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-26 23:20:00 (GMT) |
commit | f2a9d5c8378cd7eca90b3b197e2cc0989da55014 (patch) | |
tree | bdc134a961fcbc0969c0a1115174553db8384ef4 /Include/cpython | |
parent | ffedd9ad2a8be4bf82a4d8f2bac3eaee5b44191e (diff) | |
download | cpython-f2a9d5c8378cd7eca90b3b197e2cc0989da55014.zip cpython-f2a9d5c8378cd7eca90b3b197e2cc0989da55014.tar.gz cpython-f2a9d5c8378cd7eca90b3b197e2cc0989da55014.tar.bz2 |
bpo-35134: Create Include/cpython/pystate.h (GH-10733)
Move pystate.h code surrounded by "#ifndef Py_LIMITED_API"
to a new Include/cpython/pystate.h header file.
Diffstat (limited to 'Include/cpython')
-rw-r--r-- | Include/cpython/pystate.h | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h new file mode 100644 index 0000000..78e9a5e --- /dev/null +++ b/Include/cpython/pystate.h @@ -0,0 +1,272 @@ +#ifndef Py_CPYTHON_PYSTATE_H +# error "this header file must not be included directly" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int); + +/* Placeholders while working on the new configuration API + * + * See PEP 432 for final anticipated contents + */ +typedef struct { + int install_signal_handlers; /* Install signal handlers? -1 means unset */ + PyObject *argv; /* sys.argv list, can be NULL */ + PyObject *executable; /* sys.executable str */ + PyObject *prefix; /* sys.prefix str */ + PyObject *base_prefix; /* sys.base_prefix str, can be NULL */ + PyObject *exec_prefix; /* sys.exec_prefix str */ + PyObject *base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */ + PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ + PyObject *xoptions; /* sys._xoptions dict, can be NULL */ + PyObject *module_search_path; /* sys.path list */ + PyObject *pycache_prefix; /* sys.pycache_prefix str, can be NULL */ +} _PyMainInterpreterConfig; + +#define _PyMainInterpreterConfig_INIT \ + (_PyMainInterpreterConfig){.install_signal_handlers = -1} +/* Note: _PyMainInterpreterConfig_INIT sets other fields to 0/NULL */ + +typedef struct _is { + + struct _is *next; + struct _ts *tstate_head; + + int64_t id; + int64_t id_refcount; + PyThread_type_lock id_mutex; + + 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; + int fscodec_initialized; + + _PyCoreConfig core_config; + _PyMainInterpreterConfig config; +#ifdef HAVE_DLOPEN + int dlopenflags; +#endif + + 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; +} PyInterpreterState; + +/* State unique per thread */ + +/* Py_tracefunc return -1 when raising an exception, or 0 for success. */ +typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *); + +/* The following values are used for 'what' for tracefunc functions + * + * To add a new kind of trace event, also update "trace_init" in + * Python/sysmodule.c to define the Python level event name + */ +#define PyTrace_CALL 0 +#define PyTrace_EXCEPTION 1 +#define PyTrace_LINE 2 +#define PyTrace_RETURN 3 +#define PyTrace_C_CALL 4 +#define PyTrace_C_EXCEPTION 5 +#define PyTrace_C_RETURN 6 +#define PyTrace_OPCODE 7 + + +typedef struct _err_stackitem { + /* This struct represents an entry on the exception stack, which is a + * per-coroutine state. (Coroutine in the computer science sense, + * including the thread and generators). + * This ensures that the exception state is not impacted by "yields" + * from an except handler. + */ + PyObject *exc_type, *exc_value, *exc_traceback; + + struct _err_stackitem *previous_item; + +} _PyErr_StackItem; + + +typedef struct _ts { + /* See Python/ceval.c for comments explaining most fields */ + + struct _ts *prev; + struct _ts *next; + PyInterpreterState *interp; + + struct _frame *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + int stackcheck_counter; + + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + /* The exception currently being raised */ + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + /* The exception currently being handled, if no coroutines/generators + * are present. Always last element on the stack referred to be exc_info. + */ + _PyErr_StackItem exc_state; + + /* Pointer to the top of the stack of the exceptions currently + * being handled */ + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + unsigned long thread_id; /* Thread id where this tstate was created */ + + int trash_delete_nesting; + PyObject *trash_delete_later; + + /* Called when a thread state is deleted normally, but not when it + * is destroyed after fork(). + * Pain: to prevent rare but fatal shutdown errors (issue 18808), + * Thread.join() must wait for the join'ed thread's tstate to be unlinked + * from the tstate chain. That happens at the end of a thread's life, + * in pystate.c. + * The obvious way doesn't quite work: create a lock which the tstate + * unlinking code releases, and have Thread.join() wait to acquire that + * lock. The problem is that we _are_ at the end of the thread's life: + * if the thread holds the last reference to the lock, decref'ing the + * lock will delete the lock, and that may trigger arbitrary Python code + * if there's a weakref, with a callback, to the lock. But by this time + * _PyRuntime.gilstate.tstate_current is already NULL, so only the simplest + * of C code can be allowed to run (in particular it must not be possible to + * release the GIL). + * So instead of holding the lock directly, the tstate holds a weakref to + * the lock: that's the value of on_delete_data below. Decref'ing a + * weakref is harmless. + * on_delete points to _threadmodule.c's static release_sentinel() function. + * After the tstate is unlinked, release_sentinel is called with the + * weakref-to-lock (on_delete_data) argument, and release_sentinel releases + * the indirectly held lock. + */ + void (*on_delete)(void *); + void *on_delete_data; + + int coroutine_origin_tracking_depth; + + PyObject *coroutine_wrapper; + int in_coroutine_wrapper; + + PyObject *async_gen_firstiter; + PyObject *async_gen_finalizer; + + PyObject *context; + uint64_t context_ver; + + /* Unique thread state id. */ + uint64_t id; + + /* XXX signal handlers should also be here */ + +} PyThreadState; + +/* Get the current interpreter state. + + Issue a fatal error if there no current Python thread state or no current + interpreter. It cannot return NULL. + + The caller must hold the GIL.*/ +PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void); + +PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); +PyAPI_FUNC(void) _PyState_ClearModules(void); +PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); +PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *); +PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); +PyAPI_FUNC(void) _PyGILState_Reinit(void); + +/* Similar to PyThreadState_Get(), but don't issue a fatal error + * if it is NULL. */ +PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void); + +/* PyGILState */ + +/* Helper/diagnostic function - return 1 if the current thread + currently holds the GIL, 0 otherwise. + + The function returns 1 if _PyGILState_check_enabled is non-zero. */ +PyAPI_FUNC(int) PyGILState_Check(void); + +/* Get the single PyInterpreterState used by this process' GILState + implementation. + + This function doesn't check for error. Return NULL before _PyGILState_Init() + is called and after _PyGILState_Fini() is called. + + See also _PyInterpreterState_Get() and _PyInterpreterState_GET_UNSAFE(). */ +PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); + +/* The implementation of sys._current_frames() Returns a dict mapping + thread id to that thread's current frame. +*/ +PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void); + +/* Routines for advanced debuggers, requested by David Beazley. + Don't use unless you know what you are doing! */ +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Main(void); +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void); +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *); +PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *); +PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *); + +typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_); + +#ifdef __cplusplus +} +#endif |