You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

433 lines
14 KiB

  1. /*
  2. * Implementation of the Global Interpreter Lock (GIL).
  3. */
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. /* First some general settings */
  7. /* microseconds (the Python API uses seconds, though) */
  8. #define DEFAULT_INTERVAL 5000
  9. static unsigned long gil_interval = DEFAULT_INTERVAL;
  10. #define INTERVAL (gil_interval >= 1 ? gil_interval : 1)
  11. /* Enable if you want to force the switching of threads at least every `gil_interval` */
  12. #undef FORCE_SWITCHING
  13. #define FORCE_SWITCHING
  14. /*
  15. Notes about the implementation:
  16. - The GIL is just a boolean variable (gil_locked) whose access is protected
  17. by a mutex (gil_mutex), and whose changes are signalled by a condition
  18. variable (gil_cond). gil_mutex is taken for short periods of time,
  19. and therefore mostly uncontended.
  20. - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
  21. able to release the GIL on demand by another thread. A volatile boolean
  22. variable (gil_drop_request) is used for that purpose, which is checked
  23. at every turn of the eval loop. That variable is set after a wait of
  24. `interval` microseconds on `gil_cond` has timed out.
  25. [Actually, another volatile boolean variable (eval_breaker) is used
  26. which ORs several conditions into one. Volatile booleans are
  27. sufficient as inter-thread signalling means since Python is run
  28. on cache-coherent architectures only.]
  29. - A thread wanting to take the GIL will first let pass a given amount of
  30. time (`interval` microseconds) before setting gil_drop_request. This
  31. encourages a defined switching period, but doesn't enforce it since
  32. opcodes can take an arbitrary time to execute.
  33. The `interval` value is available for the user to read and modify
  34. using the Python API `sys.{get,set}switchinterval()`.
  35. - When a thread releases the GIL and gil_drop_request is set, that thread
  36. ensures that another GIL-awaiting thread gets scheduled.
  37. It does so by waiting on a condition variable (switch_cond) until
  38. the value of gil_last_holder is changed to something else than its
  39. own thread state pointer, indicating that another thread was able to
  40. take the GIL.
  41. This is meant to prohibit the latency-adverse behaviour on multi-core
  42. machines where one thread would speculatively release the GIL, but still
  43. run and end up being the first to re-acquire it, making the "timeslices"
  44. much longer than expected.
  45. (Note: this mechanism is enabled with FORCE_SWITCHING above)
  46. */
  47. #ifndef _POSIX_THREADS
  48. /* This means pthreads are not implemented in libc headers, hence the macro
  49. not present in unistd.h. But they still can be implemented as an external
  50. library (e.g. gnu pth in pthread emulation) */
  51. # ifdef HAVE_PTHREAD_H
  52. # include <pthread.h> /* _POSIX_THREADS */
  53. # endif
  54. #endif
  55. #ifdef _POSIX_THREADS
  56. /*
  57. * POSIX support
  58. */
  59. #include <pthread.h>
  60. #define ADD_MICROSECONDS(tv, interval) \
  61. do { \
  62. tv.tv_usec += (long) interval; \
  63. tv.tv_sec += tv.tv_usec / 1000000; \
  64. tv.tv_usec %= 1000000; \
  65. } while (0)
  66. /* We assume all modern POSIX systems have gettimeofday() */
  67. #ifdef GETTIMEOFDAY_NO_TZ
  68. #define GETTIMEOFDAY(ptv) gettimeofday(ptv)
  69. #else
  70. #define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
  71. #endif
  72. #define MUTEX_T pthread_mutex_t
  73. #define MUTEX_INIT(mut) \
  74. if (pthread_mutex_init(&mut, NULL)) { \
  75. Py_FatalError("pthread_mutex_init(" #mut ") failed"); };
  76. #define MUTEX_FINI(mut) \
  77. if (pthread_mutex_destroy(&mut)) { \
  78. Py_FatalError("pthread_mutex_destroy(" #mut ") failed"); };
  79. #define MUTEX_LOCK(mut) \
  80. if (pthread_mutex_lock(&mut)) { \
  81. Py_FatalError("pthread_mutex_lock(" #mut ") failed"); };
  82. #define MUTEX_UNLOCK(mut) \
  83. if (pthread_mutex_unlock(&mut)) { \
  84. Py_FatalError("pthread_mutex_unlock(" #mut ") failed"); };
  85. #define COND_T pthread_cond_t
  86. #define COND_INIT(cond) \
  87. if (pthread_cond_init(&cond, NULL)) { \
  88. Py_FatalError("pthread_cond_init(" #cond ") failed"); };
  89. #define COND_FINI(cond) \
  90. if (pthread_cond_destroy(&cond)) { \
  91. Py_FatalError("pthread_cond_destroy(" #cond ") failed"); };
  92. #define COND_SIGNAL(cond) \
  93. if (pthread_cond_signal(&cond)) { \
  94. Py_FatalError("pthread_cond_signal(" #cond ") failed"); };
  95. #define COND_WAIT(cond, mut) \
  96. if (pthread_cond_wait(&cond, &mut)) { \
  97. Py_FatalError("pthread_cond_wait(" #cond ") failed"); };
  98. #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
  99. { \
  100. int r; \
  101. struct timespec ts; \
  102. struct timeval deadline; \
  103. \
  104. GETTIMEOFDAY(&deadline); \
  105. ADD_MICROSECONDS(deadline, microseconds); \
  106. ts.tv_sec = deadline.tv_sec; \
  107. ts.tv_nsec = deadline.tv_usec * 1000; \
  108. \
  109. r = pthread_cond_timedwait(&cond, &mut, &ts); \
  110. if (r == ETIMEDOUT) \
  111. timeout_result = 1; \
  112. else if (r) \
  113. Py_FatalError("pthread_cond_timedwait(" #cond ") failed"); \
  114. else \
  115. timeout_result = 0; \
  116. } \
  117. #elif defined(NT_THREADS)
  118. /*
  119. * Windows (2000 and later, as well as (hopefully) CE) support
  120. */
  121. #include <windows.h>
  122. #define MUTEX_T CRITICAL_SECTION
  123. #define MUTEX_INIT(mut) do { \
  124. if (!(InitializeCriticalSectionAndSpinCount(&(mut), 4000))) \
  125. Py_FatalError("CreateMutex(" #mut ") failed"); \
  126. } while (0)
  127. #define MUTEX_FINI(mut) \
  128. DeleteCriticalSection(&(mut))
  129. #define MUTEX_LOCK(mut) \
  130. EnterCriticalSection(&(mut))
  131. #define MUTEX_UNLOCK(mut) \
  132. LeaveCriticalSection(&(mut))
  133. /* We emulate condition variables with a semaphore.
  134. We use a Semaphore rather than an auto-reset event, because although
  135. an auto-resent event might appear to solve the lost-wakeup bug (race
  136. condition between releasing the outer lock and waiting) because it
  137. maintains state even though a wait hasn't happened, there is still
  138. a lost wakeup problem if more than one thread are interrupted in the
  139. critical place. A semaphore solves that.
  140. Because it is ok to signal a condition variable with no one
  141. waiting, we need to keep track of the number of
  142. waiting threads. Otherwise, the semaphore's state could rise
  143. without bound.
  144. Generic emulations of the pthread_cond_* API using
  145. Win32 functions can be found on the Web.
  146. The following read can be edificating (or not):
  147. http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
  148. */
  149. typedef struct COND_T
  150. {
  151. HANDLE sem; /* the semaphore */
  152. int n_waiting; /* how many are unreleased */
  153. } COND_T;
  154. __inline static void _cond_init(COND_T *cond)
  155. {
  156. /* A semaphore with a large max value, The positive value
  157. * is only needed to catch those "lost wakeup" events and
  158. * race conditions when a timed wait elapses.
  159. */
  160. if (!(cond->sem = CreateSemaphore(NULL, 0, 1000, NULL)))
  161. Py_FatalError("CreateSemaphore() failed");
  162. cond->n_waiting = 0;
  163. }
  164. __inline static void _cond_fini(COND_T *cond)
  165. {
  166. BOOL ok = CloseHandle(cond->sem);
  167. if (!ok)
  168. Py_FatalError("CloseHandle() failed");
  169. }
  170. __inline static void _cond_wait(COND_T *cond, MUTEX_T *mut)
  171. {
  172. ++cond->n_waiting;
  173. MUTEX_UNLOCK(*mut);
  174. /* "lost wakeup bug" would occur if the caller were interrupted here,
  175. * but we are safe because we are using a semaphore wich has an internal
  176. * count.
  177. */
  178. if (WaitForSingleObject(cond->sem, INFINITE) == WAIT_FAILED)
  179. Py_FatalError("WaitForSingleObject() failed");
  180. MUTEX_LOCK(*mut);
  181. }
  182. __inline static int _cond_timed_wait(COND_T *cond, MUTEX_T *mut,
  183. int us)
  184. {
  185. DWORD r;
  186. ++cond->n_waiting;
  187. MUTEX_UNLOCK(*mut);
  188. r = WaitForSingleObject(cond->sem, us / 1000);
  189. if (r == WAIT_FAILED)
  190. Py_FatalError("WaitForSingleObject() failed");
  191. MUTEX_LOCK(*mut);
  192. if (r == WAIT_TIMEOUT)
  193. --cond->n_waiting;
  194. /* Here we have a benign race condition with _cond_signal. If the
  195. * wait operation has timed out, but before we can acquire the
  196. * mutex again to decrement n_waiting, a thread holding the mutex
  197. * still sees a positive n_waiting value and may call
  198. * ReleaseSemaphore and decrement n_waiting.
  199. * This will cause n_waiting to be decremented twice.
  200. * This is benign, though, because ReleaseSemaphore will also have
  201. * been called, leaving the semaphore state positive. We may
  202. * thus end up with semaphore in state 1, and n_waiting == -1, and
  203. * the next time someone calls _cond_wait(), that thread will
  204. * pass right through, decrementing the semaphore state and
  205. * incrementing n_waiting, thus correcting the extra _cond_signal.
  206. */
  207. return r == WAIT_TIMEOUT;
  208. }
  209. __inline static void _cond_signal(COND_T *cond) {
  210. /* NOTE: This must be called with the mutex held */
  211. if (cond->n_waiting > 0) {
  212. if (!ReleaseSemaphore(cond->sem, 1, NULL))
  213. Py_FatalError("ReleaseSemaphore() failed");
  214. --cond->n_waiting;
  215. }
  216. }
  217. #define COND_INIT(cond) \
  218. _cond_init(&(cond))
  219. #define COND_FINI(cond) \
  220. _cond_fini(&(cond))
  221. #define COND_SIGNAL(cond) \
  222. _cond_signal(&(cond))
  223. #define COND_WAIT(cond, mut) \
  224. _cond_wait(&(cond), &(mut))
  225. #define COND_TIMED_WAIT(cond, mut, us, timeout_result) do { \
  226. (timeout_result) = _cond_timed_wait(&(cond), &(mut), us); \
  227. } while (0)
  228. #else
  229. #error You need either a POSIX-compatible or a Windows system!
  230. #endif /* _POSIX_THREADS, NT_THREADS */
  231. /* Whether the GIL is already taken (-1 if uninitialized). This is atomic
  232. because it can be read without any lock taken in ceval.c. */
  233. static _Py_atomic_int gil_locked = {-1};
  234. /* Number of GIL switches since the beginning. */
  235. static unsigned long gil_switch_number = 0;
  236. /* Last PyThreadState holding / having held the GIL. This helps us know
  237. whether anyone else was scheduled after we dropped the GIL. */
  238. static _Py_atomic_address gil_last_holder = {NULL};
  239. /* This condition variable allows one or several threads to wait until
  240. the GIL is released. In addition, the mutex also protects the above
  241. variables. */
  242. static COND_T gil_cond;
  243. static MUTEX_T gil_mutex;
  244. #ifdef FORCE_SWITCHING
  245. /* This condition variable helps the GIL-releasing thread wait for
  246. a GIL-awaiting thread to be scheduled and take the GIL. */
  247. static COND_T switch_cond;
  248. static MUTEX_T switch_mutex;
  249. #endif
  250. static int gil_created(void)
  251. {
  252. return _Py_atomic_load_explicit(&gil_locked, _Py_memory_order_acquire) >= 0;
  253. }
  254. static void create_gil(void)
  255. {
  256. MUTEX_INIT(gil_mutex);
  257. #ifdef FORCE_SWITCHING
  258. MUTEX_INIT(switch_mutex);
  259. #endif
  260. COND_INIT(gil_cond);
  261. #ifdef FORCE_SWITCHING
  262. COND_INIT(switch_cond);
  263. #endif
  264. _Py_atomic_store_relaxed(&gil_last_holder, NULL);
  265. _Py_ANNOTATE_RWLOCK_CREATE(&gil_locked);
  266. _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release);
  267. }
  268. static void destroy_gil(void)
  269. {
  270. MUTEX_FINI(gil_mutex);
  271. #ifdef FORCE_SWITCHING
  272. MUTEX_FINI(switch_mutex);
  273. #endif
  274. COND_FINI(gil_cond);
  275. #ifdef FORCE_SWITCHING
  276. COND_FINI(switch_cond);
  277. #endif
  278. _Py_atomic_store_explicit(&gil_locked, -1, _Py_memory_order_release);
  279. _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
  280. }
  281. static void recreate_gil(void)
  282. {
  283. _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
  284. /* XXX should we destroy the old OS resources here? */
  285. create_gil();
  286. }
  287. static void drop_gil(PyThreadState *tstate)
  288. {
  289. if (!_Py_atomic_load_relaxed(&gil_locked))
  290. Py_FatalError("drop_gil: GIL is not locked");
  291. /* tstate is allowed to be NULL (early interpreter init) */
  292. if (tstate != NULL) {
  293. /* Sub-interpreter support: threads might have been switched
  294. under our feet using PyThreadState_Swap(). Fix the GIL last
  295. holder variable so that our heuristics work. */
  296. _Py_atomic_store_relaxed(&gil_last_holder, tstate);
  297. }
  298. MUTEX_LOCK(gil_mutex);
  299. _Py_ANNOTATE_RWLOCK_RELEASED(&gil_locked, /*is_write=*/1);
  300. _Py_atomic_store_relaxed(&gil_locked, 0);
  301. COND_SIGNAL(gil_cond);
  302. MUTEX_UNLOCK(gil_mutex);
  303. #ifdef FORCE_SWITCHING
  304. if (_Py_atomic_load_relaxed(&gil_drop_request) && tstate != NULL) {
  305. MUTEX_LOCK(switch_mutex);
  306. /* Not switched yet => wait */
  307. if (_Py_atomic_load_relaxed(&gil_last_holder) == tstate) {
  308. RESET_GIL_DROP_REQUEST();
  309. /* NOTE: if COND_WAIT does not atomically start waiting when
  310. releasing the mutex, another thread can run through, take
  311. the GIL and drop it again, and reset the condition
  312. before we even had a chance to wait for it. */
  313. COND_WAIT(switch_cond, switch_mutex);
  314. }
  315. MUTEX_UNLOCK(switch_mutex);
  316. }
  317. #endif
  318. }
  319. static void take_gil(PyThreadState *tstate)
  320. {
  321. int err;
  322. if (tstate == NULL)
  323. Py_FatalError("take_gil: NULL tstate");
  324. err = errno;
  325. MUTEX_LOCK(gil_mutex);
  326. if (!_Py_atomic_load_relaxed(&gil_locked))
  327. goto _ready;
  328. while (_Py_atomic_load_relaxed(&gil_locked)) {
  329. int timed_out = 0;
  330. unsigned long saved_switchnum;
  331. saved_switchnum = gil_switch_number;
  332. COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out);
  333. /* If we timed out and no switch occurred in the meantime, it is time
  334. to ask the GIL-holding thread to drop it. */
  335. if (timed_out &&
  336. _Py_atomic_load_relaxed(&gil_locked) &&
  337. gil_switch_number == saved_switchnum) {
  338. SET_GIL_DROP_REQUEST();
  339. }
  340. }
  341. _ready:
  342. #ifdef FORCE_SWITCHING
  343. /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */
  344. MUTEX_LOCK(switch_mutex);
  345. #endif
  346. /* We now hold the GIL */
  347. _Py_atomic_store_relaxed(&gil_locked, 1);
  348. _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil_locked, /*is_write=*/1);
  349. if (tstate != _Py_atomic_load_relaxed(&gil_last_holder)) {
  350. _Py_atomic_store_relaxed(&gil_last_holder, tstate);
  351. ++gil_switch_number;
  352. }
  353. #ifdef FORCE_SWITCHING
  354. COND_SIGNAL(switch_cond);
  355. MUTEX_UNLOCK(switch_mutex);
  356. #endif
  357. if (_Py_atomic_load_relaxed(&gil_drop_request)) {
  358. RESET_GIL_DROP_REQUEST();
  359. }
  360. if (tstate->async_exc != NULL) {
  361. _PyEval_SignalAsyncExc();
  362. }
  363. MUTEX_UNLOCK(gil_mutex);
  364. errno = err;
  365. }
  366. void _PyEval_SetSwitchInterval(unsigned long microseconds)
  367. {
  368. gil_interval = microseconds;
  369. }
  370. unsigned long _PyEval_GetSwitchInterval()
  371. {
  372. return gil_interval;
  373. }