blob: ef5189068e0c9b9c99d2447c5a53c85473bb3639 [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
8
9/* First some general settings */
10
Eric Snow2ebc5ce2017-09-07 23:51:28 -060011#define INTERVAL (_PyRuntime.ceval.gil.interval >= 1 ? _PyRuntime.ceval.gil.interval : 1)
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000012
13
14/*
15 Notes about the implementation:
16
Eric Snow2ebc5ce2017-09-07 23:51:28 -060017 - The GIL is just a boolean variable (locked) whose access is protected
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000018 by a mutex (gil_mutex), and whose changes are signalled by a condition
19 variable (gil_cond). gil_mutex is taken for short periods of time,
20 and therefore mostly uncontended.
21
22 - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
23 able to release the GIL on demand by another thread. A volatile boolean
24 variable (gil_drop_request) is used for that purpose, which is checked
25 at every turn of the eval loop. That variable is set after a wait of
26 `interval` microseconds on `gil_cond` has timed out.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020027
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000028 [Actually, another volatile boolean variable (eval_breaker) is used
29 which ORs several conditions into one. Volatile booleans are
30 sufficient as inter-thread signalling means since Python is run
31 on cache-coherent architectures only.]
32
33 - A thread wanting to take the GIL will first let pass a given amount of
34 time (`interval` microseconds) before setting gil_drop_request. This
35 encourages a defined switching period, but doesn't enforce it since
36 opcodes can take an arbitrary time to execute.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020037
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000038 The `interval` value is available for the user to read and modify
39 using the Python API `sys.{get,set}switchinterval()`.
40
41 - When a thread releases the GIL and gil_drop_request is set, that thread
42 ensures that another GIL-awaiting thread gets scheduled.
43 It does so by waiting on a condition variable (switch_cond) until
Eric Snow2ebc5ce2017-09-07 23:51:28 -060044 the value of last_holder is changed to something else than its
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000045 own thread state pointer, indicating that another thread was able to
46 take the GIL.
Serhiy Storchaka009b8112015-03-18 21:53:15 +020047
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000048 This is meant to prohibit the latency-adverse behaviour on multi-core
49 machines where one thread would speculatively release the GIL, but still
50 run and end up being the first to re-acquire it, making the "timeslices"
51 much longer than expected.
52 (Note: this mechanism is enabled with FORCE_SWITCHING above)
53*/
54
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000055#include "condvar.h"
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000056
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000057#define MUTEX_INIT(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000058 if (PyMUTEX_INIT(&(mut))) { \
59 Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000060#define MUTEX_FINI(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000061 if (PyMUTEX_FINI(&(mut))) { \
62 Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000063#define MUTEX_LOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000064 if (PyMUTEX_LOCK(&(mut))) { \
65 Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000066#define MUTEX_UNLOCK(mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000067 if (PyMUTEX_UNLOCK(&(mut))) { \
68 Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000069
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000070#define COND_INIT(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000071 if (PyCOND_INIT(&(cond))) { \
72 Py_FatalError("PyCOND_INIT(" #cond ") failed"); };
Antoine Pitrou1df15362010-09-13 14:16:46 +000073#define COND_FINI(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000074 if (PyCOND_FINI(&(cond))) { \
75 Py_FatalError("PyCOND_FINI(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000076#define COND_SIGNAL(cond) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000077 if (PyCOND_SIGNAL(&(cond))) { \
78 Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000079#define COND_WAIT(cond, mut) \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000080 if (PyCOND_WAIT(&(cond), &(mut))) { \
81 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); };
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000082#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
83 { \
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +000084 int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \
85 if (r < 0) \
86 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \
87 if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000088 timeout_result = 1; \
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000089 else \
90 timeout_result = 0; \
91 } \
92
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000093
Eric Snow2ebc5ce2017-09-07 23:51:28 -060094#define DEFAULT_INTERVAL 5000
Antoine Pitrou074e5ed2009-11-10 19:50:40 +000095
Eric Snow2ebc5ce2017-09-07 23:51:28 -060096static void _gil_initialize(struct _gil_runtime_state *state)
97{
98 _Py_atomic_int uninitialized = {-1};
99 state->locked = uninitialized;
100 state->interval = DEFAULT_INTERVAL;
101}
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000102
103static int gil_created(void)
104{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600105 return (_Py_atomic_load_explicit(&_PyRuntime.ceval.gil.locked,
106 _Py_memory_order_acquire)
107 ) >= 0;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000108}
109
110static void create_gil(void)
111{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600112 MUTEX_INIT(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000113#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600114 MUTEX_INIT(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000115#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600116 COND_INIT(_PyRuntime.ceval.gil.cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000117#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600118 COND_INIT(_PyRuntime.ceval.gil.switch_cond);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000119#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600120 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder, 0);
121 _Py_ANNOTATE_RWLOCK_CREATE(&_PyRuntime.ceval.gil.locked);
122 _Py_atomic_store_explicit(&_PyRuntime.ceval.gil.locked, 0,
123 _Py_memory_order_release);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000124}
125
Antoine Pitrou1df15362010-09-13 14:16:46 +0000126static void destroy_gil(void)
127{
Kristján Valur Jónsson187aa542012-06-05 22:17:42 +0000128 /* some pthread-like implementations tie the mutex to the cond
129 * and must have the cond destroyed first.
130 */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600131 COND_FINI(_PyRuntime.ceval.gil.cond);
132 MUTEX_FINI(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000133#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600134 COND_FINI(_PyRuntime.ceval.gil.switch_cond);
135 MUTEX_FINI(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000136#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600137 _Py_atomic_store_explicit(&_PyRuntime.ceval.gil.locked, -1,
138 _Py_memory_order_release);
139 _Py_ANNOTATE_RWLOCK_DESTROY(&_PyRuntime.ceval.gil.locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000140}
141
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000142static void recreate_gil(void)
143{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600144 _Py_ANNOTATE_RWLOCK_DESTROY(&_PyRuntime.ceval.gil.locked);
Antoine Pitrou1df15362010-09-13 14:16:46 +0000145 /* XXX should we destroy the old OS resources here? */
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000146 create_gil();
147}
148
149static void drop_gil(PyThreadState *tstate)
150{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600151 if (!_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked))
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000152 Py_FatalError("drop_gil: GIL is not locked");
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000153 /* tstate is allowed to be NULL (early interpreter init) */
154 if (tstate != NULL) {
155 /* Sub-interpreter support: threads might have been switched
156 under our feet using PyThreadState_Swap(). Fix the GIL last
157 holder variable so that our heuristics work. */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600158 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder,
159 (uintptr_t)tstate);
Antoine Pitrou6a002c02011-01-15 11:37:11 +0000160 }
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000161
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600162 MUTEX_LOCK(_PyRuntime.ceval.gil.mutex);
163 _Py_ANNOTATE_RWLOCK_RELEASED(&_PyRuntime.ceval.gil.locked, /*is_write=*/1);
164 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.locked, 0);
165 COND_SIGNAL(_PyRuntime.ceval.gil.cond);
166 MUTEX_UNLOCK(_PyRuntime.ceval.gil.mutex);
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200167
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000168#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600169 if (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil_drop_request) &&
170 tstate != NULL)
171 {
172 MUTEX_LOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000173 /* Not switched yet => wait */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600174 if (((PyThreadState*)_Py_atomic_load_relaxed(
175 &_PyRuntime.ceval.gil.last_holder)
176 ) == tstate)
177 {
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +0000178 RESET_GIL_DROP_REQUEST();
Antoine Pitroucf4cabb2009-11-11 18:11:36 +0000179 /* NOTE: if COND_WAIT does not atomically start waiting when
180 releasing the mutex, another thread can run through, take
181 the GIL and drop it again, and reset the condition
Antoine Pitroua1d23322009-11-12 22:56:02 +0000182 before we even had a chance to wait for it. */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600183 COND_WAIT(_PyRuntime.ceval.gil.switch_cond,
184 _PyRuntime.ceval.gil.switch_mutex);
Kristján Valur Jónssone75ff352012-06-18 20:30:44 +0000185 }
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600186 MUTEX_UNLOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000187 }
188#endif
189}
190
191static void take_gil(PyThreadState *tstate)
192{
193 int err;
194 if (tstate == NULL)
195 Py_FatalError("take_gil: NULL tstate");
196
197 err = errno;
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600198 MUTEX_LOCK(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000199
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600200 if (!_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked))
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000201 goto _ready;
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200202
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600203 while (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000204 int timed_out = 0;
205 unsigned long saved_switchnum;
206
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600207 saved_switchnum = _PyRuntime.ceval.gil.switch_number;
208 COND_TIMED_WAIT(_PyRuntime.ceval.gil.cond, _PyRuntime.ceval.gil.mutex,
209 INTERVAL, timed_out);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000210 /* If we timed out and no switch occurred in the meantime, it is time
211 to ask the GIL-holding thread to drop it. */
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000212 if (timed_out &&
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600213 _Py_atomic_load_relaxed(&_PyRuntime.ceval.gil.locked) &&
214 _PyRuntime.ceval.gil.switch_number == saved_switchnum) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000215 SET_GIL_DROP_REQUEST();
216 }
217 }
218_ready:
219#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600220 /* This mutex must be taken before modifying
221 _PyRuntime.ceval.gil.last_holder (see drop_gil()). */
222 MUTEX_LOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000223#endif
224 /* We now hold the GIL */
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600225 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.locked, 1);
226 _Py_ANNOTATE_RWLOCK_ACQUIRED(&_PyRuntime.ceval.gil.locked, /*is_write=*/1);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000227
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600228 if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(
229 &_PyRuntime.ceval.gil.last_holder))
230 {
231 _Py_atomic_store_relaxed(&_PyRuntime.ceval.gil.last_holder,
232 (uintptr_t)tstate);
233 ++_PyRuntime.ceval.gil.switch_number;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000234 }
Jeffrey Yasskin39370832010-05-03 19:29:34 +0000235
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000236#ifdef FORCE_SWITCHING
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600237 COND_SIGNAL(_PyRuntime.ceval.gil.switch_cond);
238 MUTEX_UNLOCK(_PyRuntime.ceval.gil.switch_mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000239#endif
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600240 if (_Py_atomic_load_relaxed(&_PyRuntime.ceval.gil_drop_request)) {
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000241 RESET_GIL_DROP_REQUEST();
242 }
243 if (tstate->async_exc != NULL) {
244 _PyEval_SignalAsyncExc();
245 }
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200246
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600247 MUTEX_UNLOCK(_PyRuntime.ceval.gil.mutex);
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000248 errno = err;
249}
250
251void _PyEval_SetSwitchInterval(unsigned long microseconds)
252{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600253 _PyRuntime.ceval.gil.interval = microseconds;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000254}
255
256unsigned long _PyEval_GetSwitchInterval()
257{
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600258 return _PyRuntime.ceval.gil.interval;
Antoine Pitrou074e5ed2009-11-10 19:50:40 +0000259}