Nuitka
The Python compiler
Loading...
Searching...
No Matches
threading.h
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifndef __NUITKA_THREADING_H__
4#define __NUITKA_THREADING_H__
5
6#if PYTHON_VERSION < 0x300
7// We share this with CPython bytecode main loop.
8PyAPI_DATA(volatile int) _Py_Ticker;
9#else
10extern volatile int _Py_Ticker;
11#define _Py_CheckInterval 20
12#endif
13
14#ifdef NUITKA_USE_PYCORE_THREAD_STATE
15
16#if PYTHON_VERSION < 0x380
17
18// Signals pending got their own indicator only in 3.8, covered by calls to do before.
19#define HAS_WORK_TO_DO(ceval, ceval2) (ceval2->pending.calls_to_do._value)
20#elif PYTHON_VERSION < 0x3d0
21#define HAS_WORK_TO_DO(ceval, ceval2) (ceval->signals_pending._value || ceval2->pending.calls_to_do._value)
22#else
23#define HAS_WORK_TO_DO(ceval, ceval2) _Py_eval_breaker_bit_is_set(tstate, _PY_SIGNALS_PENDING_BIT | _PY_CALLS_TO_DO_BIT)
24#endif
25
26#ifndef Py_GIL_DISABLED
27NUITKA_MAY_BE_UNUSED static inline bool CONSIDER_THREADING(PyThreadState *tstate) {
28#if PYTHON_VERSION < 0x390
29 _PyRuntimeState *const runtime = &_PyRuntime;
30#elif PYTHON_VERSION < 0x3d0
31 _PyRuntimeState *const runtime = tstate->interp->runtime;
32#endif
33
34#if PYTHON_VERSION < 0x3d0
35 // This was split in 2 parts in 3.9 or higher.
36 struct _ceval_runtime_state *ceval = &runtime->ceval;
37#if PYTHON_VERSION >= 0x390
38 struct _ceval_state *ceval2 = &tstate->interp->ceval;
39#else
40 struct _ceval_runtime_state *ceval2 = ceval;
41#endif
42#endif
43 // Pending signals or calls to do
44 if (HAS_WORK_TO_DO(ceval, ceval2)) {
45 int res = Py_MakePendingCalls();
46
47 if (unlikely(res < 0 && HAS_ERROR_OCCURRED(tstate))) {
48 return false;
49 }
50 }
51
52#if PYTHON_VERSION >= 0x3d0
53 /* GIL drop request */
54 if (_Py_eval_breaker_bit_is_set(tstate, _PY_GIL_DROP_REQUEST_BIT)) {
55#else
56 /* GIL drop request */
57 if (ceval2->gil_drop_request._value) {
58#endif
59 /* Give another thread a chance */
60 PyEval_SaveThread();
61 PyEval_AcquireThread(tstate);
62 }
63
64 if (unlikely(tstate->async_exc != NULL)) {
65 PyObject *async_exc = tstate->async_exc;
66 tstate->async_exc = NULL;
67
68 SET_CURRENT_EXCEPTION_TYPE0(tstate, async_exc);
69
70 return false;
71 }
72
73 return true;
74}
75#else
76NUITKA_MAY_BE_UNUSED static inline bool CONSIDER_THREADING(PyThreadState *tstate) {
77 if (unlikely(tstate->async_exc != NULL)) {
78 PyObject *async_exc = tstate->async_exc;
79 tstate->async_exc = NULL;
80
81 SET_CURRENT_EXCEPTION_TYPE0(tstate, async_exc);
82
83 return false;
84 }
85
86 return true;
87}
88
89#endif
90
91#else
92
93NUITKA_MAY_BE_UNUSED static inline bool CONSIDER_THREADING(PyThreadState *tstate) {
94 // Decrease ticker
95 if (--_Py_Ticker < 0) {
96 _Py_Ticker = _Py_CheckInterval;
97
98 int res = Py_MakePendingCalls();
99
100 if (unlikely(res < 0 && HAS_ERROR_OCCURRED(tstate))) {
101 return false;
102 }
103
104 if (PyEval_ThreadsInitialized()) {
105 // Release and acquire the GIL, it's very inefficient, because we
106 // don't even know if it makes sense to do it. A controlling thread
107 // should be used to determine if it's needed at all.
108 PyEval_SaveThread();
109 PyEval_AcquireThread(tstate);
110 }
111
112 if (unlikely(tstate->async_exc != NULL)) {
113 PyObject *async_exc = tstate->async_exc;
114 tstate->async_exc = NULL;
115
116 SET_CURRENT_EXCEPTION_TYPE0(tstate, async_exc);
117
118 return false;
119 }
120 }
121
122 return true;
123}
124
125#endif
126
127#endif
128
129// Part of "Nuitka", an optimizing Python compiler that is compatible and
130// integrates with CPython, but also works on its own.
131//
132// Licensed under the Apache License, Version 2.0 (the "License");
133// you may not use this file except in compliance with the License.
134// You may obtain a copy of the License at
135//
136// http://www.apache.org/licenses/LICENSE-2.0
137//
138// Unless required by applicable law or agreed to in writing, software
139// distributed under the License is distributed on an "AS IS" BASIS,
140// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
141// See the License for the specific language governing permissions and
142// limitations under the License.