mirror of
https://github.com/johndoe6345789/typthon.git
synced 2026-04-24 13:45:05 +00:00
- Fixed PyConfig → TyConfig globally - Fixed _Py_HandleSystemExitAndKeyboardInterrupt → _Ty_* - Fixed _Py_GetEnv, _Py_ClearArgcArgv → _Ty_* - Fixed _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED → _Ty_* - Fixed TyStatus_Ok, TyStatus_Error, TyStatus_NoMemory, TyStatus_Exit function definitions and calls Resolved linker errors. Build is much closer to completion. Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
336 lines
12 KiB
C
336 lines
12 KiB
C
#ifndef Ty_INTERNAL_PYSTATE_H
|
|
#define Ty_INTERNAL_PYSTATE_H
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef Ty_BUILD_CORE
|
|
# error "this header requires Ty_BUILD_CORE define"
|
|
#endif
|
|
|
|
#include "pycore_pythonrun.h" // _TyOS_STACK_MARGIN_SHIFT
|
|
#include "pycore_typedefs.h" // _PyRuntimeState
|
|
#include "pycore_tstate.h"
|
|
|
|
|
|
// Values for TyThreadState.state. A thread must be in the "attached" state
|
|
// before calling most Python APIs. If the GIL is enabled, then "attached"
|
|
// implies that the thread holds the GIL and "detached" implies that the
|
|
// thread does not hold the GIL (or is in the process of releasing it). In
|
|
// `--disable-gil` builds, multiple threads may be "attached" to the same
|
|
// interpreter at the same time. Only the "bound" thread may perform the
|
|
// transitions between "attached" and "detached" on its own TyThreadState.
|
|
//
|
|
// The "suspended" state is used to implement stop-the-world pauses, such as
|
|
// for cyclic garbage collection. It is only used in `--disable-gil` builds.
|
|
// The "suspended" state is similar to the "detached" state in that in both
|
|
// states the thread is not allowed to call most Python APIs. However, unlike
|
|
// the "detached" state, a thread may not transition itself out from the
|
|
// "suspended" state. Only the thread performing a stop-the-world pause may
|
|
// transition a thread from the "suspended" state back to the "detached" state.
|
|
//
|
|
// The "shutting down" state is used when the interpreter is being finalized.
|
|
// Threads in this state can't do anything other than block the OS thread.
|
|
// (See _TyThreadState_HangThread).
|
|
//
|
|
// State transition diagram:
|
|
//
|
|
// (bound thread) (stop-the-world thread)
|
|
// [attached] <-> [detached] <-> [suspended]
|
|
// | ^
|
|
// +---------------------------->---------------------------+
|
|
// (bound thread)
|
|
//
|
|
// The (bound thread) and (stop-the-world thread) labels indicate which thread
|
|
// is allowed to perform the transition.
|
|
#define _Ty_THREAD_DETACHED 0
|
|
#define _Ty_THREAD_ATTACHED 1
|
|
#define _Ty_THREAD_SUSPENDED 2
|
|
#define _Ty_THREAD_SHUTTING_DOWN 3
|
|
|
|
|
|
/* Check if the current thread is the main thread.
|
|
Use _Ty_IsMainInterpreter() to check if it's the main interpreter. */
|
|
extern int _Ty_IsMainThread(void);
|
|
|
|
// Export for '_testinternalcapi' shared extension
|
|
PyAPI_FUNC(TyInterpreterState*) _TyInterpreterState_Main(void);
|
|
|
|
static inline int
|
|
_Ty_IsMainInterpreter(TyInterpreterState *interp)
|
|
{
|
|
return (interp == _TyInterpreterState_Main());
|
|
}
|
|
|
|
extern int _Ty_IsMainInterpreterFinalizing(TyInterpreterState *interp);
|
|
|
|
// Export for _interpreters module.
|
|
PyAPI_FUNC(TyObject *) _TyInterpreterState_GetIDObject(TyInterpreterState *);
|
|
|
|
// Export for _interpreters module.
|
|
PyAPI_FUNC(int) _TyInterpreterState_SetRunningMain(TyInterpreterState *);
|
|
PyAPI_FUNC(void) _TyInterpreterState_SetNotRunningMain(TyInterpreterState *);
|
|
PyAPI_FUNC(int) _TyInterpreterState_IsRunningMain(TyInterpreterState *);
|
|
PyAPI_FUNC(void) _TyErr_SetInterpreterAlreadyRunning(void);
|
|
|
|
extern int _TyThreadState_IsRunningMain(TyThreadState *);
|
|
extern void _TyInterpreterState_ReinitRunningMain(TyThreadState *);
|
|
extern const TyConfig* _Ty_GetMainConfig(void);
|
|
|
|
|
|
/* Only handle signals on the main thread of the main interpreter. */
|
|
static inline int
|
|
_Ty_ThreadCanHandleSignals(TyInterpreterState *interp)
|
|
{
|
|
return (_Ty_IsMainThread() && _Ty_IsMainInterpreter(interp));
|
|
}
|
|
|
|
|
|
/* Variable and static inline functions for in-line access to current thread
|
|
and interpreter state */
|
|
|
|
#if defined(HAVE_THREAD_LOCAL) && !defined(Ty_BUILD_CORE_MODULE)
|
|
extern _Ty_thread_local TyThreadState *_Ty_tss_tstate;
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
extern int _TyThreadState_CheckConsistency(TyThreadState *tstate);
|
|
#endif
|
|
|
|
extern int _TyThreadState_MustExit(TyThreadState *tstate);
|
|
extern void _TyThreadState_HangThread(TyThreadState *tstate);
|
|
|
|
// Export for most shared extensions, used via _TyThreadState_GET() static
|
|
// inline function.
|
|
PyAPI_FUNC(TyThreadState *) _TyThreadState_GetCurrent(void);
|
|
|
|
/* Get the current Python thread state.
|
|
|
|
This function is unsafe: it does not check for error and it can return NULL.
|
|
|
|
The caller must hold the GIL.
|
|
|
|
See also TyThreadState_Get() and TyThreadState_GetUnchecked(). */
|
|
static inline TyThreadState*
|
|
_TyThreadState_GET(void)
|
|
{
|
|
#if defined(HAVE_THREAD_LOCAL) && !defined(Ty_BUILD_CORE_MODULE)
|
|
return _Ty_tss_tstate;
|
|
#else
|
|
return _TyThreadState_GetCurrent();
|
|
#endif
|
|
}
|
|
|
|
static inline int
|
|
_TyThreadState_IsAttached(TyThreadState *tstate)
|
|
{
|
|
return (_Ty_atomic_load_int_relaxed(&tstate->state) == _Ty_THREAD_ATTACHED);
|
|
}
|
|
|
|
// Attaches the current thread to the interpreter.
|
|
//
|
|
// This may block while acquiring the GIL (if the GIL is enabled) or while
|
|
// waiting for a stop-the-world pause (if the GIL is disabled).
|
|
//
|
|
// High-level code should generally call TyEval_RestoreThread() instead, which
|
|
// calls this function.
|
|
extern void _TyThreadState_Attach(TyThreadState *tstate);
|
|
|
|
// Detaches the current thread from the interpreter.
|
|
//
|
|
// High-level code should generally call TyEval_SaveThread() instead, which
|
|
// calls this function.
|
|
extern void _TyThreadState_Detach(TyThreadState *tstate);
|
|
|
|
// Detaches the current thread to the "suspended" state if a stop-the-world
|
|
// pause is in progress.
|
|
//
|
|
// If there is no stop-the-world pause in progress, then the thread switches
|
|
// to the "detached" state.
|
|
extern void _TyThreadState_Suspend(TyThreadState *tstate);
|
|
|
|
// Mark the thread state as "shutting down". This is used during interpreter
|
|
// and runtime finalization. The thread may no longer attach to the
|
|
// interpreter and will instead block via _TyThreadState_HangThread().
|
|
extern void _TyThreadState_SetShuttingDown(TyThreadState *tstate);
|
|
|
|
// Perform a stop-the-world pause for all threads in the all interpreters.
|
|
//
|
|
// Threads in the "attached" state are paused and transitioned to the "GC"
|
|
// state. Threads in the "detached" state switch to the "GC" state, preventing
|
|
// them from reattaching until the stop-the-world pause is complete.
|
|
//
|
|
// NOTE: This is a no-op outside of Ty_GIL_DISABLED builds.
|
|
extern void _TyEval_StopTheWorldAll(_PyRuntimeState *runtime);
|
|
extern void _TyEval_StartTheWorldAll(_PyRuntimeState *runtime);
|
|
|
|
// Perform a stop-the-world pause for threads in the specified interpreter.
|
|
//
|
|
// NOTE: This is a no-op outside of Ty_GIL_DISABLED builds.
|
|
extern PyAPI_FUNC(void) _TyEval_StopTheWorld(TyInterpreterState *interp);
|
|
extern PyAPI_FUNC(void) _TyEval_StartTheWorld(TyInterpreterState *interp);
|
|
|
|
|
|
static inline void
|
|
_Ty_EnsureFuncTstateNotNULL(const char *func, TyThreadState *tstate)
|
|
{
|
|
if (tstate == NULL) {
|
|
#ifndef Ty_GIL_DISABLED
|
|
_Ty_FatalErrorFunc(func,
|
|
"the function must be called with the GIL held, "
|
|
"after Python initialization and before Python finalization, "
|
|
"but the GIL is released (the current Python thread state is NULL)");
|
|
#else
|
|
_Ty_FatalErrorFunc(func,
|
|
"the function must be called with an active thread state, "
|
|
"after Python initialization and before Python finalization, "
|
|
"but it was called without an active thread state. "
|
|
"Are you trying to call the C API inside of a Ty_BEGIN_ALLOW_THREADS block?");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Call Ty_FatalError() if tstate is NULL
|
|
#define _Ty_EnsureTstateNotNULL(tstate) \
|
|
_Ty_EnsureFuncTstateNotNULL(__func__, (tstate))
|
|
|
|
|
|
/* Get the current interpreter state.
|
|
|
|
The function is unsafe: it does not check for error and it can return NULL.
|
|
|
|
The caller must hold the GIL.
|
|
|
|
See also TyInterpreterState_Get()
|
|
and _TyGILState_GetInterpreterStateUnsafe(). */
|
|
static inline TyInterpreterState* _TyInterpreterState_GET(void) {
|
|
TyThreadState *tstate = _TyThreadState_GET();
|
|
#ifdef Ty_DEBUG
|
|
_Ty_EnsureTstateNotNULL(tstate);
|
|
#endif
|
|
return tstate->interp;
|
|
}
|
|
|
|
|
|
// TyThreadState functions
|
|
|
|
// Export for _testinternalcapi
|
|
PyAPI_FUNC(TyThreadState *) _TyThreadState_New(
|
|
TyInterpreterState *interp,
|
|
int whence);
|
|
extern void _TyThreadState_Bind(TyThreadState *tstate);
|
|
PyAPI_FUNC(TyThreadState *) _TyThreadState_NewBound(
|
|
TyInterpreterState *interp,
|
|
int whence);
|
|
extern TyThreadState * _TyThreadState_RemoveExcept(TyThreadState *tstate);
|
|
extern void _TyThreadState_DeleteList(TyThreadState *list, int is_after_fork);
|
|
extern void _TyThreadState_ClearMimallocHeaps(TyThreadState *tstate);
|
|
|
|
// Export for '_testinternalcapi' shared extension
|
|
PyAPI_FUNC(TyObject*) _TyThreadState_GetDict(TyThreadState *tstate);
|
|
|
|
/* The implementation of sys._current_exceptions() Returns a dict mapping
|
|
thread id to that thread's current exception.
|
|
*/
|
|
extern TyObject* _PyThread_CurrentExceptions(void);
|
|
|
|
|
|
/* Other */
|
|
|
|
extern TyThreadState * _TyThreadState_Swap(
|
|
_PyRuntimeState *runtime,
|
|
TyThreadState *newts);
|
|
|
|
extern TyStatus _TyInterpreterState_Enable(_PyRuntimeState *runtime);
|
|
|
|
#ifdef HAVE_FORK
|
|
extern TyStatus _TyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
|
|
extern void _PySignal_AfterFork(void);
|
|
#endif
|
|
|
|
// Export for the stable ABI
|
|
PyAPI_FUNC(int) _PyState_AddModule(
|
|
TyThreadState *tstate,
|
|
TyObject* module,
|
|
TyModuleDef* def);
|
|
|
|
|
|
extern int _TyOS_InterruptOccurred(TyThreadState *tstate);
|
|
|
|
#define HEAD_LOCK(runtime) \
|
|
PyMutex_LockFlags(&(runtime)->interpreters.mutex, _Ty_LOCK_DONT_DETACH)
|
|
#define HEAD_UNLOCK(runtime) \
|
|
PyMutex_Unlock(&(runtime)->interpreters.mutex)
|
|
|
|
#define _Ty_FOR_EACH_TSTATE_UNLOCKED(interp, t) \
|
|
for (TyThreadState *t = interp->threads.head; t; t = t->next)
|
|
#define _Ty_FOR_EACH_TSTATE_BEGIN(interp, t) \
|
|
HEAD_LOCK(interp->runtime); \
|
|
_Ty_FOR_EACH_TSTATE_UNLOCKED(interp, t)
|
|
#define _Ty_FOR_EACH_TSTATE_END(interp) \
|
|
HEAD_UNLOCK(interp->runtime)
|
|
|
|
|
|
// Get the configuration of the current interpreter.
|
|
// The caller must hold the GIL.
|
|
// Export for test_peg_generator.
|
|
PyAPI_FUNC(const TyConfig*) _Ty_GetConfig(void);
|
|
|
|
// Get the single TyInterpreterState used by this process' GILState
|
|
// implementation.
|
|
//
|
|
// This function doesn't check for error. Return NULL before _TyGILState_Init()
|
|
// is called and after _TyGILState_Fini() is called.
|
|
//
|
|
// See also TyInterpreterState_Get() and _TyInterpreterState_GET().
|
|
extern TyInterpreterState* _TyGILState_GetInterpreterStateUnsafe(void);
|
|
|
|
extern TyObject * _Ty_GetMainModule(TyThreadState *);
|
|
extern int _Ty_CheckMainModule(TyObject *module);
|
|
|
|
#ifndef NDEBUG
|
|
/* Modern equivalent of assert(TyGILState_Check()) */
|
|
static inline void
|
|
_Ty_AssertHoldsTstateFunc(const char *func)
|
|
{
|
|
TyThreadState *tstate = _TyThreadState_GET();
|
|
_Ty_EnsureFuncTstateNotNULL(func, tstate);
|
|
}
|
|
#define _Ty_AssertHoldsTstate() _Ty_AssertHoldsTstateFunc(__func__)
|
|
#else
|
|
#define _Ty_AssertHoldsTstate()
|
|
#endif
|
|
|
|
#if !_Ty__has_builtin(__builtin_frame_address) && !defined(__GNUC__) && !defined(_MSC_VER)
|
|
static uintptr_t return_pointer_as_int(char* p) {
|
|
return (uintptr_t)p;
|
|
}
|
|
#endif
|
|
|
|
static inline uintptr_t
|
|
_Ty_get_machine_stack_pointer(void) {
|
|
#if _Ty__has_builtin(__builtin_frame_address) || defined(__GNUC__)
|
|
return (uintptr_t)__builtin_frame_address(0);
|
|
#elif defined(_MSC_VER)
|
|
return (uintptr_t)_AddressOfReturnAddress();
|
|
#else
|
|
char here;
|
|
/* Avoid compiler warning about returning stack address */
|
|
return return_pointer_as_int(&here);
|
|
#endif
|
|
}
|
|
|
|
static inline intptr_t
|
|
_Ty_RecursionLimit_GetMargin(TyThreadState *tstate)
|
|
{
|
|
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
|
|
assert(_tstate->c_stack_hard_limit != 0);
|
|
intptr_t here_addr = _Ty_get_machine_stack_pointer();
|
|
return Ty_ARITHMETIC_RIGHT_SHIFT(intptr_t, here_addr - (intptr_t)_tstate->c_stack_soft_limit, _TyOS_STACK_MARGIN_SHIFT);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* !Ty_INTERNAL_PYSTATE_H */
|