blob: 56944b89237fb49af3eee31aa2f2f7c695871bdc [file] [log] [blame]
Antoine Pitrou074e5ed2009-11-10 19:50:40 +00001/*
2 * Implementation of the Global Interpreter Lock (GIL).
3 */
4
5#include <stdlib.h>
6#include <errno.h>
7
Victor Stinner27e2d1f2018-11-01 00:52:28 +01008#include "pycore_atomic.h"
Antoine Pitrou074e5ed2009-11-10 19:50:40 +00009
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000010
11/*
12 Notes about the implementation:
13
Eric Snow2ebc5ce2017-09-07 23:51:28 -060014 - The GIL is just a boolean variable (locked) whose access is protected
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000015 by a mutex (gil_mutex), and whose changes are signalled by a condition
16 variable (gil_cond). gil_mutex is taken for short periods of time,
17 and therefore mostly uncontended.
18
19 - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
20 able to release the GIL on demand by another thread. A volatile boolean
21 variable (gil_drop_request) is used for that purpose, which is checked
22 at every turn of the eval loop. That variable is set after a wait of
23 `interval` microseconds on `gil_cond` has timed out.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020024
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000025 [Actually, another volatile boolean variable (eval_breaker) is used
26 which ORs several conditions into one. Volatile booleans are
27 sufficient as inter-thread signalling means since Python is run
28 on cache-coherent architectures only.]
29
30 - A thread wanting to take the GIL will first let pass a given amount of
31 time (`interval` microseconds) before setting gil_drop_request. This
32 encourages a defined switching period, but doesn't enforce it since
33 opcodes can take an arbitrary time to execute.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020034
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000035 The `interval` value is available for the user to read and modify
36 using the Python API `sys.{get,set}switchinterval()`.
37
38 - When a thread releases the GIL and gil_drop_request is set, that thread
39 ensures that another GIL-awaiting thread gets scheduled.
40 It does so by waiting on a condition variable (switch_cond) until
Eric Snow2ebc5ce2017-09-07 23:51:28 -060041 the value of last_holder is changed to something else than its
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000042 own thread state pointer, indicating that another thread was able to
43 take the GIL.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020044
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000045 This is meant to prohibit the latency-adverse behaviour on multi-core
46 machines where one thread would speculatively release the GIL, but still
47 run and end up being the first to re-acquire it, making the "timeslices"
48 much longer than expected.
49 (Note: this mechanism is enabled with FORCE_SWITCHING above)
50*/
51
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000052#include "condvar.h"
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000053
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000054#define MUTEX_INIT(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000055 if (PyMUTEX_INIT(&(mut))) { \
56 Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000057#define MUTEX_FINI(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000058 if (PyMUTEX_FINI(&(mut))) { \
59 Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000060#define MUTEX_LOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000061 if (PyMUTEX_LOCK(&(mut))) { \
62 Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000063#define MUTEX_UNLOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000064 if (PyMUTEX_UNLOCK(&(mut))) { \
65 Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000066
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000067#define COND_INIT(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000068 if (PyCOND_INIT(&(cond))) { \
69 Py_FatalError("PyCOND_INIT(" #cond ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000070#define COND_FINI(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000071 if (PyCOND_FINI(&(cond))) { \
72 Py_FatalError("PyCOND_FINI(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000073#define COND_SIGNAL(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000074 if (PyCOND_SIGNAL(&(cond))) { \
75 Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000076#define COND_WAIT(cond, mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000077 if (PyCOND_WAIT(&(cond), &(mut))) { \
78 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000079#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
80 { \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000081 int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \
82 if (r < 0) \
83 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \
84 if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000085 timeout_result = 1; \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000086 else \
87 timeout_result = 0; \
88 } \
89
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000090
Eric Snow2ebc5ce2017-09-07 23:51:28 -060091#define DEFAULT_INTERVAL 5000
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000092
Victor Stinner09532fe2019-05-10 23:39:09 +020093static void _gil_initialize(struct _gil_runtime_state *gil)
Eric Snow2ebc5ce2017-09-07 23:51:28 -060094{
95 _Py_atomic_int uninitialized = {-1};
Victor Stinner09532fe2019-05-10 23:39:09 +020096 gil->locked = uninitialized;
97 gil->interval = DEFAULT_INTERVAL;
Eric Snow2ebc5ce2017-09-07 23:51:28 -060098}
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000099
Victor Stinner09532fe2019-05-10 23:39:09 +0200100static int gil_created(struct _gil_runtime_state *gil)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000101{
Victor Stinner09532fe2019-05-10 23:39:09 +0200102 return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000103}
104
Victor Stinner09532fe2019-05-10 23:39:09 +0200105static void create_gil(struct _gil_runtime_state *gil)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000106{
Victor Stinner09532fe2019-05-10 23:39:09 +0200107 MUTEX_INIT(gil->mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000108#ifdef FORCE_SWITCHING
Victor Stinner09532fe2019-05-10 23:39:09 +0200109 MUTEX_INIT(gil->switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000110#endif
Victor Stinner09532fe2019-05-10 23:39:09 +0200111 COND_INIT(gil->cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000112#ifdef FORCE_SWITCHING
Victor Stinner09532fe2019-05-10 23:39:09 +0200113 COND_INIT(gil->switch_cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000114#endif
Victor Stinner09532fe2019-05-10 23:39:09 +0200115 _Py_atomic_store_relaxed(&gil->last_holder, 0);
116 _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked);
117 _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000118}
119
Victor Stinner09532fe2019-05-10 23:39:09 +0200120static void destroy_gil(struct _gil_runtime_state *gil)
Antoine Pitrou1df15362010-09-13 14:16:46 +0000121{
Kristján Valur Jónsson187aa542012-06-05 22:17:42 +0000122 /* some pthread-like implementations tie the mutex to the cond
123 * and must have the cond destroyed first.
124 */
Victor Stinner09532fe2019-05-10 23:39:09 +0200125 COND_FINI(gil->cond);
126 MUTEX_FINI(gil->mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000127#ifdef FORCE_SWITCHING
Victor Stinner09532fe2019-05-10 23:39:09 +0200128 COND_FINI(gil->switch_cond);
129 MUTEX_FINI(gil->switch_mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000130#endif
Victor Stinner09532fe2019-05-10 23:39:09 +0200131 _Py_atomic_store_explicit(&gil->locked, -1,
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600132 _Py_memory_order_release);
Victor Stinner09532fe2019-05-10 23:39:09 +0200133 _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000134}
135
Victor Stinner09532fe2019-05-10 23:39:09 +0200136static void recreate_gil(struct _gil_runtime_state *gil)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000137{
Victor Stinner09532fe2019-05-10 23:39:09 +0200138 _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000139 /* XXX should we destroy the old OS resources here? */
Victor Stinner09532fe2019-05-10 23:39:09 +0200140 create_gil(gil);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000141}
142
Victor Stinner09532fe2019-05-10 23:39:09 +0200143static void
Victor Stinner0b1e3302020-05-05 16:14:31 +0200144drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
145 PyThreadState *tstate)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000146{
Victor Stinner7be4e352020-05-05 20:27:47 +0200147#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
148 struct _gil_runtime_state *gil = &ceval2->gil;
149#else
Victor Stinnere225beb2019-06-03 18:14:24 +0200150 struct _gil_runtime_state *gil = &ceval->gil;
Victor Stinner7be4e352020-05-05 20:27:47 +0200151#endif
Victor Stinner09532fe2019-05-10 23:39:09 +0200152 if (!_Py_atomic_load_relaxed(&gil->locked)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000153 Py_FatalError("drop_gil: GIL is not locked");
Victor Stinner09532fe2019-05-10 23:39:09 +0200154 }
155
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000156 /* tstate is allowed to be NULL (early interpreter init) */
157 if (tstate != NULL) {
158 /* Sub-interpreter support: threads might have been switched
159 under our feet using PyThreadState_Swap(). Fix the GIL last
160 holder variable so that our heuristics work. */
Victor Stinner09532fe2019-05-10 23:39:09 +0200161 _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000162 }
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000163
Victor Stinner09532fe2019-05-10 23:39:09 +0200164 MUTEX_LOCK(gil->mutex);
165 _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1);
166 _Py_atomic_store_relaxed(&gil->locked, 0);
167 COND_SIGNAL(gil->cond);
168 MUTEX_UNLOCK(gil->mutex);
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200169
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000170#ifdef FORCE_SWITCHING
Victor Stinner0b1e3302020-05-05 16:14:31 +0200171 if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) {
Victor Stinner09532fe2019-05-10 23:39:09 +0200172 MUTEX_LOCK(gil->switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000173 /* Not switched yet => wait */
Victor Stinner09532fe2019-05-10 23:39:09 +0200174 if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600175 {
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200176 assert(is_tstate_valid(tstate));
177 RESET_GIL_DROP_REQUEST(tstate->interp);
Antoine Pitroucf4cabb2009-11-11 18:11:36 +0000178 /* NOTE: if COND_WAIT does not atomically start waiting when
179 releasing the mutex, another thread can run through, take
180 the GIL and drop it again, and reset the condition
Antoine Pitroua1d23322009-11-12 22:56:02 +0000181 before we even had a chance to wait for it. */
Victor Stinner09532fe2019-05-10 23:39:09 +0200182 COND_WAIT(gil->switch_cond, gil->switch_mutex);
183 }
184 MUTEX_UNLOCK(gil->switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000185 }
186#endif
187}
188
Victor Stinner85f5a692020-03-09 22:12:04 +0100189
190/* Check if a Python thread must exit immediately, rather than taking the GIL
191 if Py_Finalize() has been called.
192
193 When this function is called by a daemon thread after Py_Finalize() has been
194 called, the GIL does no longer exist.
195
196 tstate must be non-NULL. */
197static inline int
198tstate_must_exit(PyThreadState *tstate)
199{
200 /* bpo-39877: Access _PyRuntime directly rather than using
201 tstate->interp->runtime to support calls from Python daemon threads.
202 After Py_Finalize() has been called, tstate can be a dangling pointer:
203 point to PyThreadState freed memory. */
Victor Stinnera36adfa2020-03-19 19:48:25 +0100204 PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);
Victor Stinner85f5a692020-03-09 22:12:04 +0100205 return (finalizing != NULL && finalizing != tstate);
206}
207
208
Victor Stinnereb4e2ae2020-03-08 11:57:45 +0100209/* Take the GIL.
210
211 The function saves errno at entry and restores its value at exit.
212
213 tstate must be non-NULL. */
Victor Stinner09532fe2019-05-10 23:39:09 +0200214static void
Victor Stinner85f5a692020-03-09 22:12:04 +0100215take_gil(PyThreadState *tstate)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000216{
Victor Stinnereb4e2ae2020-03-08 11:57:45 +0100217 int err = errno;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000218
Victor Stinner85f5a692020-03-09 22:12:04 +0100219 assert(tstate != NULL);
220
Victor Stinner85f5a692020-03-09 22:12:04 +0100221 if (tstate_must_exit(tstate)) {
Victor Stinner9229eee2020-03-09 23:10:53 +0100222 /* bpo-39877: If Py_Finalize() has been called and tstate is not the
223 thread which called Py_Finalize(), exit immediately the thread.
224
225 This code path can be reached by a daemon thread after Py_Finalize()
226 completes. In this case, tstate is a dangling pointer: points to
227 PyThreadState freed memory. */
Victor Stinner85f5a692020-03-09 22:12:04 +0100228 PyThread_exit_thread();
229 }
230
Victor Stinnerda2914d2020-03-20 09:29:08 +0100231 assert(is_tstate_valid(tstate));
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200232 PyInterpreterState *interp = tstate->interp;
233 struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
Victor Stinner0b1e3302020-05-05 16:14:31 +0200234 struct _ceval_state *ceval2 = &interp->ceval;
Victor Stinner7be4e352020-05-05 20:27:47 +0200235#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
236 struct _gil_runtime_state *gil = &ceval2->gil;
237#else
Victor Stinnere225beb2019-06-03 18:14:24 +0200238 struct _gil_runtime_state *gil = &ceval->gil;
Victor Stinner7be4e352020-05-05 20:27:47 +0200239#endif
Victor Stinner85f5a692020-03-09 22:12:04 +0100240
241 /* Check that _PyEval_InitThreads() was called to create the lock */
242 assert(gil_created(gil));
243
Victor Stinner09532fe2019-05-10 23:39:09 +0200244 MUTEX_LOCK(gil->mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000245
Victor Stinner09532fe2019-05-10 23:39:09 +0200246 if (!_Py_atomic_load_relaxed(&gil->locked)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000247 goto _ready;
Victor Stinner09532fe2019-05-10 23:39:09 +0200248 }
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200249
Victor Stinner09532fe2019-05-10 23:39:09 +0200250 while (_Py_atomic_load_relaxed(&gil->locked)) {
Victor Stinnera36adfa2020-03-19 19:48:25 +0100251 unsigned long saved_switchnum = gil->switch_number;
Victor Stinner09532fe2019-05-10 23:39:09 +0200252
253 unsigned long interval = (gil->interval >= 1 ? gil->interval : 1);
Victor Stinnera36adfa2020-03-19 19:48:25 +0100254 int timed_out = 0;
Victor Stinner09532fe2019-05-10 23:39:09 +0200255 COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out);
Victor Stinnera36adfa2020-03-19 19:48:25 +0100256
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000257 /* If we timed out and no switch occurred in the meantime, it is time
258 to ask the GIL-holding thread to drop it. */
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000259 if (timed_out &&
Victor Stinner09532fe2019-05-10 23:39:09 +0200260 _Py_atomic_load_relaxed(&gil->locked) &&
261 gil->switch_number == saved_switchnum)
262 {
Victor Stinnera36adfa2020-03-19 19:48:25 +0100263 if (tstate_must_exit(tstate)) {
264 MUTEX_UNLOCK(gil->mutex);
265 PyThread_exit_thread();
266 }
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200267 assert(is_tstate_valid(tstate));
Victor Stinnera36adfa2020-03-19 19:48:25 +0100268
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200269 SET_GIL_DROP_REQUEST(interp);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000270 }
271 }
Victor Stinner85f5a692020-03-09 22:12:04 +0100272
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000273_ready:
274#ifdef FORCE_SWITCHING
Victor Stinner09532fe2019-05-10 23:39:09 +0200275 /* This mutex must be taken before modifying gil->last_holder:
276 see drop_gil(). */
277 MUTEX_LOCK(gil->switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000278#endif
279 /* We now hold the GIL */
Victor Stinner09532fe2019-05-10 23:39:09 +0200280 _Py_atomic_store_relaxed(&gil->locked, 1);
281 _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000282
Victor Stinner09532fe2019-05-10 23:39:09 +0200283 if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) {
284 _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
285 ++gil->switch_number;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000286 }
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000287
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000288#ifdef FORCE_SWITCHING
Victor Stinner09532fe2019-05-10 23:39:09 +0200289 COND_SIGNAL(gil->switch_cond);
290 MUTEX_UNLOCK(gil->switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000291#endif
Victor Stinner5a3a71d2020-03-19 17:40:12 +0100292
Victor Stinnera36adfa2020-03-19 19:48:25 +0100293 if (tstate_must_exit(tstate)) {
294 /* bpo-36475: If Py_Finalize() has been called and tstate is not
295 the thread which called Py_Finalize(), exit immediately the
296 thread.
297
298 This code path can be reached by a daemon thread which was waiting
299 in take_gil() while the main thread called
300 wait_for_thread_shutdown() from Py_Finalize(). */
301 MUTEX_UNLOCK(gil->mutex);
Victor Stinner0b1e3302020-05-05 16:14:31 +0200302 drop_gil(ceval, ceval2, tstate);
Victor Stinnera36adfa2020-03-19 19:48:25 +0100303 PyThread_exit_thread();
304 }
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200305 assert(is_tstate_valid(tstate));
Victor Stinnera36adfa2020-03-19 19:48:25 +0100306
Victor Stinner0b1e3302020-05-05 16:14:31 +0200307 if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) {
Victor Stinnerb54a99d2020-04-08 23:35:05 +0200308 RESET_GIL_DROP_REQUEST(interp);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000309 }
Victor Stinner5a3a71d2020-03-19 17:40:12 +0100310 else {
311 /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there
Victor Stinnerda2914d2020-03-20 09:29:08 +0100312 is a pending signal: signal received by another thread which cannot
Victor Stinner5a3a71d2020-03-19 17:40:12 +0100313 handle signals.
314
315 Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */
Victor Stinner299b8c62020-05-05 17:40:18 +0200316 COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
Victor Stinner5a3a71d2020-03-19 17:40:12 +0100317 }
Victor Stinner29356e02020-03-18 03:04:33 +0100318
Victor Stinner29356e02020-03-18 03:04:33 +0100319 /* Don't access tstate if the thread must exit */
Victor Stinnera36adfa2020-03-19 19:48:25 +0100320 if (tstate->async_exc != NULL) {
Victor Stinner56bfdeb2020-03-18 09:26:25 +0100321 _PyEval_SignalAsyncExc(tstate);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000322 }
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200323
Victor Stinner09532fe2019-05-10 23:39:09 +0200324 MUTEX_UNLOCK(gil->mutex);
Victor Stinnereb4e2ae2020-03-08 11:57:45 +0100325
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000326 errno = err;
327}
328
329void _PyEval_SetSwitchInterval(unsigned long microseconds)
330{
Victor Stinner7be4e352020-05-05 20:27:47 +0200331#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
332 PyInterpreterState *interp = PyInterpreterState_Get();
333 struct _gil_runtime_state *gil = &interp->ceval.gil;
334#else
335 struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
336#endif
337 gil->interval = microseconds;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000338}
339
340unsigned long _PyEval_GetSwitchInterval()
341{
Victor Stinner7be4e352020-05-05 20:27:47 +0200342#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
343 PyInterpreterState *interp = PyInterpreterState_Get();
344 struct _gil_runtime_state *gil = &interp->ceval.gil;
345#else
346 struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
347#endif
348 return gil->interval;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000349}