Mercurial > cpython-lru_cache-weakref
annotate Python/ceval_gil.h @ 87690:66c1c9f32567 default tip
Add use_weakref option to functools.lru_cache
The use_weakref option makes lru_cache create weak references to the function
arguments when creating the cache key, which prevents them from staying in the
memory forever even after all other references to them are gone.
This is a proof of concept for http://bugs.python.org/issue19859
| author | Radomir Dopieralski <devel@sheep.art.pl> |
|---|---|
| date | Tue, 03 Dec 2013 16:02:48 +0100 |
| parents | 978326f98316 |
| children |
| rev | line source |
|---|---|
| 57175 | 1 /* |
| 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 | |
| 11 /* microseconds (the Python API uses seconds, though) */ | |
| 12 #define DEFAULT_INTERVAL 5000 | |
| 13 static unsigned long gil_interval = DEFAULT_INTERVAL; | |
| 14 #define INTERVAL (gil_interval >= 1 ? gil_interval : 1) | |
| 15 | |
| 16 /* Enable if you want to force the switching of threads at least every `gil_interval` */ | |
| 17 #undef FORCE_SWITCHING | |
| 18 #define FORCE_SWITCHING | |
| 19 | |
| 20 | |
| 21 /* | |
| 22 Notes about the implementation: | |
| 23 | |
| 24 - The GIL is just a boolean variable (gil_locked) whose access is protected | |
| 25 by a mutex (gil_mutex), and whose changes are signalled by a condition | |
| 26 variable (gil_cond). gil_mutex is taken for short periods of time, | |
| 27 and therefore mostly uncontended. | |
| 28 | |
| 29 - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be | |
| 30 able to release the GIL on demand by another thread. A volatile boolean | |
| 31 variable (gil_drop_request) is used for that purpose, which is checked | |
| 32 at every turn of the eval loop. That variable is set after a wait of | |
| 33 `interval` microseconds on `gil_cond` has timed out. | |
| 34 | |
| 35 [Actually, another volatile boolean variable (eval_breaker) is used | |
| 36 which ORs several conditions into one. Volatile booleans are | |
| 37 sufficient as inter-thread signalling means since Python is run | |
| 38 on cache-coherent architectures only.] | |
| 39 | |
| 40 - A thread wanting to take the GIL will first let pass a given amount of | |
| 41 time (`interval` microseconds) before setting gil_drop_request. This | |
| 42 encourages a defined switching period, but doesn't enforce it since | |
| 43 opcodes can take an arbitrary time to execute. | |
| 44 | |
| 45 The `interval` value is available for the user to read and modify | |
| 46 using the Python API `sys.{get,set}switchinterval()`. | |
| 47 | |
| 48 - When a thread releases the GIL and gil_drop_request is set, that thread | |
| 49 ensures that another GIL-awaiting thread gets scheduled. | |
| 50 It does so by waiting on a condition variable (switch_cond) until | |
| 51 the value of gil_last_holder is changed to something else than its | |
| 52 own thread state pointer, indicating that another thread was able to | |
| 53 take the GIL. | |
| 54 | |
| 55 This is meant to prohibit the latency-adverse behaviour on multi-core | |
| 56 machines where one thread would speculatively release the GIL, but still | |
| 57 run and end up being the first to re-acquire it, making the "timeslices" | |
| 58 much longer than expected. | |
| 59 (Note: this mechanism is enabled with FORCE_SWITCHING above) | |
| 60 */ | |
| 61 | |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
62 #include "condvar.h" |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
63 #ifndef Py_HAVE_CONDVAR |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
64 #error You need either a POSIX-compatible or a Windows system! |
| 57175 | 65 #endif |
| 66 | |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
67 #define MUTEX_T PyMUTEX_T |
| 57175 | 68 #define MUTEX_INIT(mut) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
69 if (PyMUTEX_INIT(&(mut))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
70 Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); }; |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
71 #define MUTEX_FINI(mut) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
72 if (PyMUTEX_FINI(&(mut))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
73 Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); }; |
| 57175 | 74 #define MUTEX_LOCK(mut) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
75 if (PyMUTEX_LOCK(&(mut))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
76 Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); }; |
| 57175 | 77 #define MUTEX_UNLOCK(mut) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
78 if (PyMUTEX_UNLOCK(&(mut))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
79 Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); }; |
| 57175 | 80 |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
81 #define COND_T PyCOND_T |
| 57175 | 82 #define COND_INIT(cond) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
83 if (PyCOND_INIT(&(cond))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
84 Py_FatalError("PyCOND_INIT(" #cond ") failed"); }; |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
85 #define COND_FINI(cond) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
86 if (PyCOND_FINI(&(cond))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
87 Py_FatalError("PyCOND_FINI(" #cond ") failed"); }; |
| 57175 | 88 #define COND_SIGNAL(cond) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
89 if (PyCOND_SIGNAL(&(cond))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
90 Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); }; |
| 57175 | 91 #define COND_WAIT(cond, mut) \ |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
92 if (PyCOND_WAIT(&(cond), &(mut))) { \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
93 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); }; |
| 57175 | 94 #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ |
| 95 { \ | |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
96 int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
97 if (r < 0) \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
98 Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \ |
|
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
99 if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \ |
| 57175 | 100 timeout_result = 1; \ |
| 101 else \ | |
| 102 timeout_result = 0; \ | |
| 103 } \ | |
| 104 | |
| 105 | |
| 106 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
107 /* Whether the GIL is already taken (-1 if uninitialized). This is atomic |
| 57175 | 108 because it can be read without any lock taken in ceval.c. */ |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
109 static _Py_atomic_int gil_locked = {-1}; |
| 57175 | 110 /* Number of GIL switches since the beginning. */ |
| 111 static unsigned long gil_switch_number = 0; | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
112 /* Last PyThreadState holding / having held the GIL. This helps us know |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
113 whether anyone else was scheduled after we dropped the GIL. */ |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
114 static _Py_atomic_address gil_last_holder = {NULL}; |
| 57175 | 115 |
| 116 /* This condition variable allows one or several threads to wait until | |
| 117 the GIL is released. In addition, the mutex also protects the above | |
| 118 variables. */ | |
| 119 static COND_T gil_cond; | |
| 120 static MUTEX_T gil_mutex; | |
| 121 | |
| 122 #ifdef FORCE_SWITCHING | |
| 123 /* This condition variable helps the GIL-releasing thread wait for | |
| 124 a GIL-awaiting thread to be scheduled and take the GIL. */ | |
| 125 static COND_T switch_cond; | |
| 126 static MUTEX_T switch_mutex; | |
| 127 #endif | |
| 128 | |
| 129 | |
| 130 static int gil_created(void) | |
| 131 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
132 return _Py_atomic_load_explicit(&gil_locked, _Py_memory_order_acquire) >= 0; |
| 57175 | 133 } |
| 134 | |
| 135 static void create_gil(void) | |
| 136 { | |
| 137 MUTEX_INIT(gil_mutex); | |
| 138 #ifdef FORCE_SWITCHING | |
| 139 MUTEX_INIT(switch_mutex); | |
| 140 #endif | |
| 141 COND_INIT(gil_cond); | |
| 142 #ifdef FORCE_SWITCHING | |
| 143 COND_INIT(switch_cond); | |
| 144 #endif | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
145 _Py_atomic_store_relaxed(&gil_last_holder, NULL); |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
146 _Py_ANNOTATE_RWLOCK_CREATE(&gil_locked); |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
147 _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release); |
| 57175 | 148 } |
| 149 | |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
150 static void destroy_gil(void) |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
151 { |
|
77365
6d146e2ae9a9
Signal condition variables with the mutex held. Destroy condition variables
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
67603
diff
changeset
|
152 /* some pthread-like implementations tie the mutex to the cond |
|
6d146e2ae9a9
Signal condition variables with the mutex held. Destroy condition variables
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
67603
diff
changeset
|
153 * and must have the cond destroyed first. |
|
6d146e2ae9a9
Signal condition variables with the mutex held. Destroy condition variables
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
67603
diff
changeset
|
154 */ |
|
6d146e2ae9a9
Signal condition variables with the mutex held. Destroy condition variables
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
67603
diff
changeset
|
155 COND_FINI(gil_cond); |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
156 MUTEX_FINI(gil_mutex); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
157 #ifdef FORCE_SWITCHING |
|
77365
6d146e2ae9a9
Signal condition variables with the mutex held. Destroy condition variables
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
67603
diff
changeset
|
158 COND_FINI(switch_cond); |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
159 MUTEX_FINI(switch_mutex); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
160 #endif |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
161 _Py_atomic_store_explicit(&gil_locked, -1, _Py_memory_order_release); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
162 _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
163 } |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
164 |
| 57175 | 165 static void recreate_gil(void) |
| 166 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
167 _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
168 /* XXX should we destroy the old OS resources here? */ |
| 57175 | 169 create_gil(); |
| 170 } | |
| 171 | |
| 172 static void drop_gil(PyThreadState *tstate) | |
| 173 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
174 if (!_Py_atomic_load_relaxed(&gil_locked)) |
| 57175 | 175 Py_FatalError("drop_gil: GIL is not locked"); |
|
67603
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
176 /* tstate is allowed to be NULL (early interpreter init) */ |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
177 if (tstate != NULL) { |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
178 /* Sub-interpreter support: threads might have been switched |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
179 under our feet using PyThreadState_Swap(). Fix the GIL last |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
180 holder variable so that our heuristics work. */ |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
181 _Py_atomic_store_relaxed(&gil_last_holder, tstate); |
|
2930393f0bbb
Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2.
Antoine Pitrou <solipsis@pitrou.net>
parents:
64709
diff
changeset
|
182 } |
| 57175 | 183 |
| 184 MUTEX_LOCK(gil_mutex); | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
185 _Py_ANNOTATE_RWLOCK_RELEASED(&gil_locked, /*is_write=*/1); |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
186 _Py_atomic_store_relaxed(&gil_locked, 0); |
| 57175 | 187 COND_SIGNAL(gil_cond); |
| 188 MUTEX_UNLOCK(gil_mutex); | |
| 189 | |
| 190 #ifdef FORCE_SWITCHING | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
191 if (_Py_atomic_load_relaxed(&gil_drop_request) && tstate != NULL) { |
| 57175 | 192 MUTEX_LOCK(switch_mutex); |
| 193 /* Not switched yet => wait */ | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
194 if (_Py_atomic_load_relaxed(&gil_last_holder) == tstate) { |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
195 RESET_GIL_DROP_REQUEST(); |
|
57191
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
196 /* NOTE: if COND_WAIT does not atomically start waiting when |
|
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
197 releasing the mutex, another thread can run through, take |
|
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
198 the GIL and drop it again, and reset the condition |
|
57203
f9a50cede6a9
Try to strengthen condition-waiting under Windows.
Antoine Pitrou <solipsis@pitrou.net>
parents:
57191
diff
changeset
|
199 before we even had a chance to wait for it. */ |
| 57175 | 200 COND_WAIT(switch_cond, switch_mutex); |
|
77513
978326f98316
Issue #15038: Optimize python Locks on Windows
Kristján Valur Jónsson <kristjan@ccpgames.com>
parents:
77365
diff
changeset
|
201 } |
| 57175 | 202 MUTEX_UNLOCK(switch_mutex); |
| 203 } | |
| 204 #endif | |
| 205 } | |
| 206 | |
| 207 static void take_gil(PyThreadState *tstate) | |
| 208 { | |
| 209 int err; | |
| 210 if (tstate == NULL) | |
| 211 Py_FatalError("take_gil: NULL tstate"); | |
| 212 | |
| 213 err = errno; | |
| 214 MUTEX_LOCK(gil_mutex); | |
| 215 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
216 if (!_Py_atomic_load_relaxed(&gil_locked)) |
| 57175 | 217 goto _ready; |
| 218 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
219 while (_Py_atomic_load_relaxed(&gil_locked)) { |
| 57175 | 220 int timed_out = 0; |
| 221 unsigned long saved_switchnum; | |
| 222 | |
| 223 saved_switchnum = gil_switch_number; | |
| 224 COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out); | |
| 225 /* If we timed out and no switch occurred in the meantime, it is time | |
| 226 to ask the GIL-holding thread to drop it. */ | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
227 if (timed_out && |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
228 _Py_atomic_load_relaxed(&gil_locked) && |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
229 gil_switch_number == saved_switchnum) { |
| 57175 | 230 SET_GIL_DROP_REQUEST(); |
| 231 } | |
| 232 } | |
| 233 _ready: | |
| 234 #ifdef FORCE_SWITCHING | |
| 235 /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */ | |
| 236 MUTEX_LOCK(switch_mutex); | |
| 237 #endif | |
| 238 /* We now hold the GIL */ | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
239 _Py_atomic_store_relaxed(&gil_locked, 1); |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
240 _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil_locked, /*is_write=*/1); |
| 57175 | 241 |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
242 if (tstate != _Py_atomic_load_relaxed(&gil_last_holder)) { |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
243 _Py_atomic_store_relaxed(&gil_last_holder, tstate); |
| 57175 | 244 ++gil_switch_number; |
| 245 } | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
246 |
| 57175 | 247 #ifdef FORCE_SWITCHING |
| 248 COND_SIGNAL(switch_cond); | |
| 249 MUTEX_UNLOCK(switch_mutex); | |
| 250 #endif | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
251 if (_Py_atomic_load_relaxed(&gil_drop_request)) { |
| 57175 | 252 RESET_GIL_DROP_REQUEST(); |
| 253 } | |
| 254 if (tstate->async_exc != NULL) { | |
| 255 _PyEval_SignalAsyncExc(); | |
| 256 } | |
| 257 | |
| 258 MUTEX_UNLOCK(gil_mutex); | |
| 259 errno = err; | |
| 260 } | |
| 261 | |
| 262 void _PyEval_SetSwitchInterval(unsigned long microseconds) | |
| 263 { | |
| 264 gil_interval = microseconds; | |
| 265 } | |
| 266 | |
| 267 unsigned long _PyEval_GetSwitchInterval() | |
| 268 { | |
| 269 return gil_interval; | |
| 270 } |
