Mercurial > cpython-lru_cache-weakref
annotate Python/ceval_gil.h @ 73323:dad02a080bbc
Improve byte-compilation in packaging to be independent of -O or -B.
The code I fixed to comply with PEP 3147 still had one bug: When run
under python -O, some paths for pyc files would be pyo, because I called
imp.cache_from_source without explicit debug_override argument in some
places, and under -O that would return .pyo (this is well explained in
the imp docs). Now all code (util.byte_compile, build_py, install_lib)
can create .pyo files according to options given by users,
without interference from the calling Python’s own optimize mode.
On a related topic, I also removed the code that prevented byte
compilation under python -B. The rationale is that packaging gives
control over the creation of pyc files to the user with its own explicit
option, and the behavior should not be changed if the calling Python
happens to run with -B for whatever reason. I will argue that this is a
bug fix and ask to be allowed to backport this change to distutils.
Finally, I moved one nugget of information about the --compile and
--optimize options from the source into the doc. It clears up a
misunderstanding that I (and maybe other people) had.
| author | Éric Araujo <merwok@netwok.org> |
|---|---|
| date | Thu, 03 Nov 2011 05:08:28 +0100 |
| parents | 2930393f0bbb |
| children | 6d146e2ae9a9 |
| 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 | |
| 62 #ifndef _POSIX_THREADS | |
| 63 /* This means pthreads are not implemented in libc headers, hence the macro | |
| 64 not present in unistd.h. But they still can be implemented as an external | |
| 65 library (e.g. gnu pth in pthread emulation) */ | |
| 66 # ifdef HAVE_PTHREAD_H | |
| 67 # include <pthread.h> /* _POSIX_THREADS */ | |
| 68 # endif | |
| 69 #endif | |
| 70 | |
| 71 | |
| 72 #ifdef _POSIX_THREADS | |
| 73 | |
| 74 /* | |
| 75 * POSIX support | |
| 76 */ | |
| 77 | |
| 78 #include <pthread.h> | |
| 79 | |
| 80 #define ADD_MICROSECONDS(tv, interval) \ | |
| 81 do { \ | |
| 82 tv.tv_usec += (long) interval; \ | |
| 83 tv.tv_sec += tv.tv_usec / 1000000; \ | |
| 84 tv.tv_usec %= 1000000; \ | |
| 85 } while (0) | |
| 86 | |
| 87 /* We assume all modern POSIX systems have gettimeofday() */ | |
| 88 #ifdef GETTIMEOFDAY_NO_TZ | |
| 89 #define GETTIMEOFDAY(ptv) gettimeofday(ptv) | |
| 90 #else | |
| 91 #define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL) | |
| 92 #endif | |
| 93 | |
| 94 #define MUTEX_T pthread_mutex_t | |
| 95 #define MUTEX_INIT(mut) \ | |
| 96 if (pthread_mutex_init(&mut, NULL)) { \ | |
| 97 Py_FatalError("pthread_mutex_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
|
98 #define MUTEX_FINI(mut) \ |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
99 if (pthread_mutex_destroy(&mut)) { \ |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
100 Py_FatalError("pthread_mutex_destroy(" #mut ") failed"); }; |
| 57175 | 101 #define MUTEX_LOCK(mut) \ |
| 102 if (pthread_mutex_lock(&mut)) { \ | |
| 103 Py_FatalError("pthread_mutex_lock(" #mut ") failed"); }; | |
| 104 #define MUTEX_UNLOCK(mut) \ | |
| 105 if (pthread_mutex_unlock(&mut)) { \ | |
| 106 Py_FatalError("pthread_mutex_unlock(" #mut ") failed"); }; | |
| 107 | |
| 108 #define COND_T pthread_cond_t | |
| 109 #define COND_INIT(cond) \ | |
| 110 if (pthread_cond_init(&cond, NULL)) { \ | |
| 111 Py_FatalError("pthread_cond_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
|
112 #define COND_FINI(cond) \ |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
113 if (pthread_cond_destroy(&cond)) { \ |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
114 Py_FatalError("pthread_cond_destroy(" #cond ") failed"); }; |
| 57175 | 115 #define COND_SIGNAL(cond) \ |
| 116 if (pthread_cond_signal(&cond)) { \ | |
| 117 Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; | |
| 118 #define COND_WAIT(cond, mut) \ | |
| 119 if (pthread_cond_wait(&cond, &mut)) { \ | |
| 120 Py_FatalError("pthread_cond_wait(" #cond ") failed"); }; | |
| 121 #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ | |
| 122 { \ | |
| 123 int r; \ | |
| 124 struct timespec ts; \ | |
| 125 struct timeval deadline; \ | |
| 126 \ | |
| 127 GETTIMEOFDAY(&deadline); \ | |
| 128 ADD_MICROSECONDS(deadline, microseconds); \ | |
| 129 ts.tv_sec = deadline.tv_sec; \ | |
| 130 ts.tv_nsec = deadline.tv_usec * 1000; \ | |
| 131 \ | |
| 132 r = pthread_cond_timedwait(&cond, &mut, &ts); \ | |
| 133 if (r == ETIMEDOUT) \ | |
| 134 timeout_result = 1; \ | |
| 135 else if (r) \ | |
| 136 Py_FatalError("pthread_cond_timedwait(" #cond ") failed"); \ | |
| 137 else \ | |
| 138 timeout_result = 0; \ | |
| 139 } \ | |
| 140 | |
| 141 #elif defined(NT_THREADS) | |
| 142 | |
| 143 /* | |
| 144 * Windows (2000 and later, as well as (hopefully) CE) support | |
| 145 */ | |
| 146 | |
| 147 #include <windows.h> | |
| 148 | |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
149 #define MUTEX_T CRITICAL_SECTION |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
150 #define MUTEX_INIT(mut) do { \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
151 if (!(InitializeCriticalSectionAndSpinCount(&(mut), 4000))) \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
152 Py_FatalError("CreateMutex(" #mut ") failed"); \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
153 } while (0) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
154 #define MUTEX_FINI(mut) \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
155 DeleteCriticalSection(&(mut)) |
| 57175 | 156 #define MUTEX_LOCK(mut) \ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
157 EnterCriticalSection(&(mut)) |
| 57175 | 158 #define MUTEX_UNLOCK(mut) \ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
159 LeaveCriticalSection(&(mut)) |
| 57175 | 160 |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
161 /* We emulate condition variables with a semaphore. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
162 We use a Semaphore rather than an auto-reset event, because although |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
163 an auto-resent event might appear to solve the lost-wakeup bug (race |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
164 condition between releasing the outer lock and waiting) because it |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
165 maintains state even though a wait hasn't happened, there is still |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
166 a lost wakeup problem if more than one thread are interrupted in the |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
167 critical place. A semaphore solves that. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
168 Because it is ok to signal a condition variable with no one |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
169 waiting, we need to keep track of the number of |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
170 waiting threads. Otherwise, the semaphore's state could rise |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
171 without bound. |
|
57191
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
172 |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
173 Generic emulations of the pthread_cond_* API using |
|
57191
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
174 Win32 functions can be found on the Web. |
|
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
175 The following read can be edificating (or not): |
|
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
176 http://www.cse.wustl.edu/~schmidt/win32-cv-1.html |
|
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
177 */ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
178 typedef struct COND_T |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
179 { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
180 HANDLE sem; /* the semaphore */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
181 int n_waiting; /* how many are unreleased */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
182 } COND_T; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
183 |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
184 __inline static void _cond_init(COND_T *cond) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
185 { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
186 /* A semaphore with a large max value, The positive value |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
187 * is only needed to catch those "lost wakeup" events and |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
188 * race conditions when a timed wait elapses. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
189 */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
190 if (!(cond->sem = CreateSemaphore(NULL, 0, 1000, NULL))) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
191 Py_FatalError("CreateSemaphore() failed"); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
192 cond->n_waiting = 0; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
193 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
194 |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
195 __inline static void _cond_fini(COND_T *cond) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
196 { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
197 BOOL ok = CloseHandle(cond->sem); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
198 if (!ok) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
199 Py_FatalError("CloseHandle() failed"); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
200 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
201 |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
202 __inline static void _cond_wait(COND_T *cond, MUTEX_T *mut) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
203 { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
204 ++cond->n_waiting; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
205 MUTEX_UNLOCK(*mut); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
206 /* "lost wakeup bug" would occur if the caller were interrupted here, |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
207 * but we are safe because we are using a semaphore wich has an internal |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
208 * count. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
209 */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
210 if (WaitForSingleObject(cond->sem, INFINITE) == WAIT_FAILED) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
211 Py_FatalError("WaitForSingleObject() failed"); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
212 MUTEX_LOCK(*mut); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
213 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
214 |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
215 __inline static int _cond_timed_wait(COND_T *cond, MUTEX_T *mut, |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
216 int us) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
217 { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
218 DWORD r; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
219 ++cond->n_waiting; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
220 MUTEX_UNLOCK(*mut); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
221 r = WaitForSingleObject(cond->sem, us / 1000); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
222 if (r == WAIT_FAILED) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
223 Py_FatalError("WaitForSingleObject() failed"); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
224 MUTEX_LOCK(*mut); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
225 if (r == WAIT_TIMEOUT) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
226 --cond->n_waiting; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
227 /* Here we have a benign race condition with _cond_signal. If the |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
228 * wait operation has timed out, but before we can acquire the |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
229 * mutex again to decrement n_waiting, a thread holding the mutex |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
230 * still sees a positive n_waiting value and may call |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
231 * ReleaseSemaphore and decrement n_waiting. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
232 * This will cause n_waiting to be decremented twice. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
233 * This is benign, though, because ReleaseSemaphore will also have |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
234 * been called, leaving the semaphore state positive. We may |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
235 * thus end up with semaphore in state 1, and n_waiting == -1, and |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
236 * the next time someone calls _cond_wait(), that thread will |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
237 * pass right through, decrementing the semaphore state and |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
238 * incrementing n_waiting, thus correcting the extra _cond_signal. |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
239 */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
240 return r == WAIT_TIMEOUT; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
241 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
242 |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
243 __inline static void _cond_signal(COND_T *cond) { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
244 /* NOTE: This must be called with the mutex held */ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
245 if (cond->n_waiting > 0) { |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
246 if (!ReleaseSemaphore(cond->sem, 1, NULL)) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
247 Py_FatalError("ReleaseSemaphore() failed"); |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
248 --cond->n_waiting; |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
249 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
250 } |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
251 |
| 57175 | 252 #define COND_INIT(cond) \ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
253 _cond_init(&(cond)) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
254 #define COND_FINI(cond) \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
255 _cond_fini(&(cond)) |
| 57175 | 256 #define COND_SIGNAL(cond) \ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
257 _cond_signal(&(cond)) |
| 57175 | 258 #define COND_WAIT(cond, mut) \ |
|
63911
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
259 _cond_wait(&(cond), &(mut)) |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
260 #define COND_TIMED_WAIT(cond, mut, us, timeout_result) do { \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
261 (timeout_result) = _cond_timed_wait(&(cond), &(mut), us); \ |
|
39092f86b0af
Issue #8411: new condition variable emulation under Windows for the new GIL,
Antoine Pitrou <solipsis@pitrou.net>
parents:
61184
diff
changeset
|
262 } while (0) |
| 57175 | 263 |
| 264 #else | |
| 265 | |
| 266 #error You need either a POSIX-compatible or a Windows system! | |
| 267 | |
| 268 #endif /* _POSIX_THREADS, NT_THREADS */ | |
| 269 | |
| 270 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
271 /* Whether the GIL is already taken (-1 if uninitialized). This is atomic |
| 57175 | 272 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
|
273 static _Py_atomic_int gil_locked = {-1}; |
| 57175 | 274 /* Number of GIL switches since the beginning. */ |
| 275 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
|
276 /* 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
|
277 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
|
278 static _Py_atomic_address gil_last_holder = {NULL}; |
| 57175 | 279 |
| 280 /* This condition variable allows one or several threads to wait until | |
| 281 the GIL is released. In addition, the mutex also protects the above | |
| 282 variables. */ | |
| 283 static COND_T gil_cond; | |
| 284 static MUTEX_T gil_mutex; | |
| 285 | |
| 286 #ifdef FORCE_SWITCHING | |
| 287 /* This condition variable helps the GIL-releasing thread wait for | |
| 288 a GIL-awaiting thread to be scheduled and take the GIL. */ | |
| 289 static COND_T switch_cond; | |
| 290 static MUTEX_T switch_mutex; | |
| 291 #endif | |
| 292 | |
| 293 | |
| 294 static int gil_created(void) | |
| 295 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
296 return _Py_atomic_load_explicit(&gil_locked, _Py_memory_order_acquire) >= 0; |
| 57175 | 297 } |
| 298 | |
| 299 static void create_gil(void) | |
| 300 { | |
| 301 MUTEX_INIT(gil_mutex); | |
| 302 #ifdef FORCE_SWITCHING | |
| 303 MUTEX_INIT(switch_mutex); | |
| 304 #endif | |
| 305 COND_INIT(gil_cond); | |
| 306 #ifdef FORCE_SWITCHING | |
| 307 COND_INIT(switch_cond); | |
| 308 #endif | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
309 _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
|
310 _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
|
311 _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release); |
| 57175 | 312 } |
| 313 | |
|
64709
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
314 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
|
315 { |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
316 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
|
317 #ifdef FORCE_SWITCHING |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
318 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
|
319 #endif |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
320 COND_FINI(gil_cond); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
321 #ifdef FORCE_SWITCHING |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
322 COND_FINI(switch_cond); |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
323 #endif |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
324 _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
|
325 _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
|
326 } |
|
557e2537c9ae
Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
Antoine Pitrou <solipsis@pitrou.net>
parents:
63911
diff
changeset
|
327 |
| 57175 | 328 static void recreate_gil(void) |
| 329 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
330 _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
|
331 /* XXX should we destroy the old OS resources here? */ |
| 57175 | 332 create_gil(); |
| 333 } | |
| 334 | |
| 335 static void drop_gil(PyThreadState *tstate) | |
| 336 { | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
337 if (!_Py_atomic_load_relaxed(&gil_locked)) |
| 57175 | 338 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
|
339 /* 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
|
340 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
|
341 /* 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
|
342 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
|
343 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
|
344 _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
|
345 } |
| 57175 | 346 |
| 347 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
|
348 _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
|
349 _Py_atomic_store_relaxed(&gil_locked, 0); |
| 57175 | 350 COND_SIGNAL(gil_cond); |
| 351 MUTEX_UNLOCK(gil_mutex); | |
| 352 | |
| 353 #ifdef FORCE_SWITCHING | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
354 if (_Py_atomic_load_relaxed(&gil_drop_request) && tstate != NULL) { |
| 57175 | 355 MUTEX_LOCK(switch_mutex); |
| 356 /* 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
|
357 if (_Py_atomic_load_relaxed(&gil_last_holder) == tstate) { |
|
57203
f9a50cede6a9
Try to strengthen condition-waiting under Windows.
Antoine Pitrou <solipsis@pitrou.net>
parents:
57191
diff
changeset
|
358 RESET_GIL_DROP_REQUEST(); |
|
57191
c717fe993085
Our condition variable emulation under Windows is imperfect, which
Antoine Pitrou <solipsis@pitrou.net>
parents:
57175
diff
changeset
|
359 /* 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
|
360 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
|
361 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
|
362 before we even had a chance to wait for it. */ |
| 57175 | 363 COND_WAIT(switch_cond, switch_mutex); |
|
57203
f9a50cede6a9
Try to strengthen condition-waiting under Windows.
Antoine Pitrou <solipsis@pitrou.net>
parents:
57191
diff
changeset
|
364 } |
| 57175 | 365 MUTEX_UNLOCK(switch_mutex); |
| 366 } | |
| 367 #endif | |
| 368 } | |
| 369 | |
| 370 static void take_gil(PyThreadState *tstate) | |
| 371 { | |
| 372 int err; | |
| 373 if (tstate == NULL) | |
| 374 Py_FatalError("take_gil: NULL tstate"); | |
| 375 | |
| 376 err = errno; | |
| 377 MUTEX_LOCK(gil_mutex); | |
| 378 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
379 if (!_Py_atomic_load_relaxed(&gil_locked)) |
| 57175 | 380 goto _ready; |
| 381 | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
382 while (_Py_atomic_load_relaxed(&gil_locked)) { |
| 57175 | 383 int timed_out = 0; |
| 384 unsigned long saved_switchnum; | |
| 385 | |
| 386 saved_switchnum = gil_switch_number; | |
| 387 COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out); | |
| 388 /* If we timed out and no switch occurred in the meantime, it is time | |
| 389 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
|
390 if (timed_out && |
|
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
391 _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
|
392 gil_switch_number == saved_switchnum) { |
| 57175 | 393 SET_GIL_DROP_REQUEST(); |
| 394 } | |
| 395 } | |
| 396 _ready: | |
| 397 #ifdef FORCE_SWITCHING | |
| 398 /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */ | |
| 399 MUTEX_LOCK(switch_mutex); | |
| 400 #endif | |
| 401 /* 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
|
402 _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
|
403 _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil_locked, /*is_write=*/1); |
| 57175 | 404 |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
405 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
|
406 _Py_atomic_store_relaxed(&gil_last_holder, tstate); |
| 57175 | 407 ++gil_switch_number; |
| 408 } | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
409 |
| 57175 | 410 #ifdef FORCE_SWITCHING |
| 411 COND_SIGNAL(switch_cond); | |
| 412 MUTEX_UNLOCK(switch_mutex); | |
| 413 #endif | |
|
61184
4fd3ab5fa71d
Make (most of) Python's tests pass under Thread Sanitizer.
Jeffrey Yasskin <jyasskin@gmail.com>
parents:
57203
diff
changeset
|
414 if (_Py_atomic_load_relaxed(&gil_drop_request)) { |
| 57175 | 415 RESET_GIL_DROP_REQUEST(); |
| 416 } | |
| 417 if (tstate->async_exc != NULL) { | |
| 418 _PyEval_SignalAsyncExc(); | |
| 419 } | |
| 420 | |
| 421 MUTEX_UNLOCK(gil_mutex); | |
| 422 errno = err; | |
| 423 } | |
| 424 | |
| 425 void _PyEval_SetSwitchInterval(unsigned long microseconds) | |
| 426 { | |
| 427 gil_interval = microseconds; | |
| 428 } | |
| 429 | |
| 430 unsigned long _PyEval_GetSwitchInterval() | |
| 431 { | |
| 432 return gil_interval; | |
| 433 } |
