blob: f2d5fdba0153643ba35aa62aef52dc77637b19c8 [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
10/* First some general settings */
11
Eric Snow2ebc5ce2017-09-07 23:51:28 -060012#define INTERVAL (_PyRuntime.ceval.gil.interval >= 1 ? _PyRuntime.ceval.gil.interval : 1)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000013
14
15/*
16 Notes about the implementation:
17
Eric Snow2ebc5ce2017-09-07 23:51:28 -060018 - The GIL is just a boolean variable (locked) whose access is protected
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000019 by a mutex (gil_mutex), and whose changes are signalled by a condition
20 variable (gil_cond). gil_mutex is taken for short periods of time,
21 and therefore mostly uncontended.
22
23 - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
24 able to release the GIL on demand by another thread. A volatile boolean
25 variable (gil_drop_request) is used for that purpose, which is checked
26 at every turn of the eval loop. That variable is set after a wait of
27 `interval` microseconds on `gil_cond` has timed out.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020028
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000029 [Actually, another volatile boolean variable (eval_breaker) is used
30 which ORs several conditions into one. Volatile booleans are
31 sufficient as inter-thread signalling means since Python is run
32 on cache-coherent architectures only.]
33
34 - A thread wanting to take the GIL will first let pass a given amount of
35 time (`interval` microseconds) before setting gil_drop_request. This
36 encourages a defined switching period, but doesn't enforce it since
37 opcodes can take an arbitrary time to execute.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020038
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000039 The `interval` value is available for the user to read and modify
40 using the Python API `sys.{get,set}switchinterval()`.
41
42 - When a thread releases the GIL and gil_drop_request is set, that thread
43 ensures that another GIL-awaiting thread gets scheduled.
44 It does so by waiting on a condition variable (switch_cond) until
Eric Snow2ebc5ce2017-09-07 23:51:28 -060045 the value of last_holder is changed to something else than its
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000046 own thread state pointer, indicating that another thread was able to
47 take the GIL.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020048
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000049 This is meant to prohibit the latency-adverse behaviour on multi-core
50 machines where one thread would speculatively release the GIL, but still
51 run and end up being the first to re-acquire it, making the "timeslices"
52 much longer than expected.
53 (Note: this mechanism is enabled with FORCE_SWITCHING above)
54*/
55
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000056#include "condvar.h"
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000057
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000058#define MUTEX_INIT(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000059 if (PyMUTEX_INIT(&(mut))) { \
60 Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000061#define MUTEX_FINI(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000062 if (PyMUTEX_FINI(&(mut))) { \
63 Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000064#define MUTEX_LOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000065 if (PyMUTEX_LOCK(&(mut))) { \
66 Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000067#define MUTEX_UNLOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000068 if (PyMUTEX_UNLOCK(&(mut))) { \
69 Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000070
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000071#define COND_INIT(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000072 if (PyCOND_INIT(&(cond))) { \
73 Py_FatalError("PyCOND_INIT(" #cond ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000074#define COND_FINI(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000075 if (PyCOND_FINI(&(cond))) { \
76 Py_FatalError("PyCOND_FINI(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000077#define COND_SIGNAL(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000078 if (PyCOND_SIGNAL(&(cond))) { \
79 Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000080#define COND_WAIT(cond, mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000081 if (PyCOND_WAIT(&(cond), &(mut))) { \
82 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000083#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
84 { \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000085 int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \
86 if (r < 0) \
87 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \
88 if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000089 timeout_result = 1; \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000090 else \
91 timeout_result = 0; \
92 } \
93
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000094
Eric Snow2ebc5ce2017-09-07 23:51:28 -060095#define DEFAULT_INTERVAL 5000
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000096
Eric Snow2ebc5ce2017-09-07 23:51:28 -060097static void _gil_initialize(struct _gil_runtime_state *state)
98{
99 _Py_atomic_int uninitialized = {-1};
100 state->locked = uninitialized;
101 state->interval = DEFAULT_INTERVAL;
102}
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000103
104static int gil_created(void)
105{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600106 return (_Py_atomic_load_explicit(&_PyRuntime.ceval.gil.locked,
107 _Py_memory_order_acquire)
108 ) >= 0;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000109}
110
111static void create_gil(void)
112{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600113 MUTEX_INIT(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000114#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600115 MUTEX_INIT(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000116#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600117 COND_INIT(_PyRuntime.ceval.gil.cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000118#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600119 COND_INIT(_PyRuntime.ceval.gil.switch_cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000120#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600121 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder, 0);
122 _Py_ANNOTATE_RWLOCK_CREATE(&_PyRuntime.ceval.gil.locked);
123 _Py_atomic_store_explicit(&_PyRuntime.ceval.gil.locked, 0,
124 _Py_memory_order_release);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000125}
126
Antoine Pitrou1df15362010-09-13 14:16:46 +0000127static void destroy_gil(void)
128{
Kristján Valur Jónsson187aa542012-06-05 22:17:42 +0000129 /* some pthread-like implementations tie the mutex to the cond
130 * and must have the cond destroyed first.
131 */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600132 COND_FINI(_PyRuntime.ceval.gil.cond);
133 MUTEX_FINI(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000134#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600135 COND_FINI(_PyRuntime.ceval.gil.switch_cond);
136 MUTEX_FINI(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000137#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600138 _Py_atomic_store_explicit(&_PyRuntime.ceval.gil.locked, -1,
139 _Py_memory_order_release);
140 _Py_ANNOTATE_RWLOCK_DESTROY(&_PyRuntime.ceval.gil.locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000141}
142
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000143static void recreate_gil(void)
144{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600145 _Py_ANNOTATE_RWLOCK_DESTROY(&_PyRuntime.ceval.gil.locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000146 /* XXX should we destroy the old OS resources here? */
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000147 create_gil();
148}
149
150static void drop_gil(PyThreadState *tstate)
151{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600152 if (!_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked))
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000153 Py_FatalError("drop_gil: GIL is not locked");
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000154 /* tstate is allowed to be NULL (early interpreter init) */
155 if (tstate != NULL) {
156 /* Sub-interpreter support: threads might have been switched
157 under our feet using PyThreadState_Swap(). Fix the GIL last
158 holder variable so that our heuristics work. */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600159 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder,
160 (uintptr_t)tstate);
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000161 }
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000162
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600163 MUTEX_LOCK(_PyRuntime.ceval.gil.mutex);
164 _Py_ANNOTATE_RWLOCK_RELEASED(&_PyRuntime.ceval.gil.locked, /*is_write=*/1);
165 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.locked, 0);
166 COND_SIGNAL(_PyRuntime.ceval.gil.cond);
167 MUTEX_UNLOCK(_PyRuntime.ceval.gil.mutex);
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200168
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000169#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600170 if (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil_drop_request) &&
171 tstate != NULL)
172 {
173 MUTEX_LOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000174 /* Not switched yet => wait */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600175 if (((PyThreadState*)_Py_atomic_load_relaxed(
176 &_PyRuntime.ceval.gil.last_holder)
177 ) == tstate)
178 {
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +0000179 RESET_GIL_DROP_REQUEST();
Antoine Pitroucf4cabb2009-11-11 18:11:36 +0000180 /* NOTE: if COND_WAIT does not atomically start waiting when
181 releasing the mutex, another thread can run through, take
182 the GIL and drop it again, and reset the condition
Antoine Pitroua1d23322009-11-12 22:56:02 +0000183 before we even had a chance to wait for it. */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600184 COND_WAIT(_PyRuntime.ceval.gil.switch_cond,
185 _PyRuntime.ceval.gil.switch_mutex);
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +0000186 }
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600187 MUTEX_UNLOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000188 }
189#endif
190}
191
192static void take_gil(PyThreadState *tstate)
193{
194 int err;
195 if (tstate == NULL)
196 Py_FatalError("take_gil: NULL tstate");
197
198 err = errno;
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600199 MUTEX_LOCK(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000200
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600201 if (!_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked))
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000202 goto _ready;
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200203
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600204 while (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000205 int timed_out = 0;
206 unsigned long saved_switchnum;
207
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600208 saved_switchnum = _PyRuntime.ceval.gil.switch_number;
209 COND_TIMED_WAIT(_PyRuntime.ceval.gil.cond, _PyRuntime.ceval.gil.mutex,
210 INTERVAL, timed_out);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000211 /* If we timed out and no switch occurred in the meantime, it is time
212 to ask the GIL-holding thread to drop it. */
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000213 if (timed_out &&
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600214 _Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked) &&
215 _PyRuntime.ceval.gil.switch_number == saved_switchnum) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000216 SET_GIL_DROP_REQUEST();
217 }
218 }
219_ready:
220#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600221 /* This mutex must be taken before modifying
222 _PyRuntime.ceval.gil.last_holder (see drop_gil()). */
223 MUTEX_LOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000224#endif
225 /* We now hold the GIL */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600226 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.locked, 1);
227 _Py_ANNOTATE_RWLOCK_ACQUIRED(&_PyRuntime.ceval.gil.locked, /*is_write=*/1);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000228
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600229 if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(
230 &_PyRuntime.ceval.gil.last_holder))
231 {
232 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder,
233 (uintptr_t)tstate);
234 ++_PyRuntime.ceval.gil.switch_number;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000235 }
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000236
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000237#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600238 COND_SIGNAL(_PyRuntime.ceval.gil.switch_cond);
239 MUTEX_UNLOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000240#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600241 if (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil_drop_request)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000242 RESET_GIL_DROP_REQUEST();
243 }
244 if (tstate->async_exc != NULL) {
245 _PyEval_SignalAsyncExc();
246 }
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200247
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600248 MUTEX_UNLOCK(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000249 errno = err;
250}
251
252void _PyEval_SetSwitchInterval(unsigned long microseconds)
253{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600254 _PyRuntime.ceval.gil.interval = microseconds;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000255}
256
257unsigned long _PyEval_GetSwitchInterval()
258{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600259 return _PyRuntime.ceval.gil.interval;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000260}