Jit/runtime_support.cpp (70 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #include "Jit/runtime_support.h" #include "Python.h" #include "internal/pycore_ceval.h" #include "internal/pycore_pyerrors.h" #include "internal/pycore_pystate.h" extern "C" { void take_gil(struct _ceval_runtime_state*, PyThreadState*); void drop_gil(struct _ceval_runtime_state*, PyThreadState*); void exit_thread_if_finalizing(_PyRuntimeState* runtime, PyThreadState* tstate); int make_pending_calls(_PyRuntimeState* runtime); int handle_signals(_PyRuntimeState* runtime); } namespace jit { PyObject g_iterDoneSentinel = { _PyObject_EXTRA_INIT kImmortalInitialCount, nullptr}; PyObject* invokeIterNext(PyObject* iterator) { PyObject* val = (*iterator->ob_type->tp_iternext)(iterator); if (val != nullptr) { return val; } if (PyErr_Occurred()) { if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { return nullptr; } PyErr_Clear(); } Py_INCREF(&g_iterDoneSentinel); return &g_iterDoneSentinel; } // This duplicates the logic found at the beginning of the dispatch loop in // _PyEval_EvalFrameDefault PyObject* runPeriodicTasks() { PyThreadState* tstate = PyThreadState_GET(); _PyRuntimeState* const runtime = &_PyRuntime; struct _ceval_runtime_state* const ceval = &_PyRuntime.ceval; if (_Py_atomic_load_relaxed(&ceval->signals_pending)) { if (handle_signals(runtime) != 0) { return nullptr; } } if (_Py_atomic_load_relaxed(&ceval->pending.calls_to_do)) { if (make_pending_calls(runtime) != 0) { return nullptr; } } if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { /* Give another thread a chance */ if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { Py_FatalError("ceval: tstate mix-up"); } drop_gil(ceval, tstate); /* Other threads may run now */ take_gil(ceval, tstate); /* Check if we should make a quick exit. */ if (runtime->finalizing != NULL && !_Py_CURRENTLY_FINALIZING(runtime, tstate)) { drop_gil(&runtime->ceval, tstate); PyThread_exit_thread(); } if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { Py_FatalError("ceval: orphan tstate"); } } /* Check for asynchronous exceptions. */ if (tstate->async_exc != nullptr) { PyObject* exc = tstate->async_exc; tstate->async_exc = nullptr; UNSIGNAL_ASYNC_EXC(ceval); _PyErr_SetNone(tstate, exc); Py_DECREF(exc); return nullptr; } return Py_True; } } // namespace jit