[Python-checkins] r76192 - sandbox/trunk/newgil/Python/ceval_gil.h
antoine.pitrou
python-checkins at python.org
Tue Nov 10 20:23:36 CET 2009
Author: antoine.pitrou
Date: Tue Nov 10 20:23:36 2009
New Revision: 76192
Log:
A bit more documentation
Modified:
sandbox/trunk/newgil/Python/ceval_gil.h
Modified: sandbox/trunk/newgil/Python/ceval_gil.h
==============================================================================
--- sandbox/trunk/newgil/Python/ceval_gil.h (original)
+++ sandbox/trunk/newgil/Python/ceval_gil.h Tue Nov 10 20:23:36 2009
@@ -20,32 +20,43 @@
/*
Notes about the implementation:
-
+
- The GIL is just a boolean variable (gil_locked) whose access is protected
- by a mutex, and whose changes are signalled by a condition variable. The
- mutex itself is rarely taken and, therefore, mostly uncontended.
+ by a mutex (gil_mutex), and whose changes are signalled by a condition
+ variable (gil_cond). gil_mutex is taken for short periods of time,
+ and therefore mostly uncontended.
- In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
able to release the GIL on demand by another thread. A volatile boolean
variable (gil_drop_request) is used for that purpose, which is checked
- at every turn of the eval loop.
+ at every turn of the eval loop. That variable is set after a wait of
+ `interval` microseconds on `gil_cond` has timed out.
[Actually, another volatile boolean variable (eval_breaker) is used
- which aggregates several conditions into one. Volatile booleans are
- ok as signalling means since Python is run on cache-coherent
- architectures only.]
-
- - A thread wanting to take the GIL will first wait for a given amount of
- time before setting gil_drop_request. This amount of time defines the
- ideal thread switching period. It is available for the user to read
- and modify using `sys.{get,set}switchinterval()`.
-
- - Forced thread switching when releasing the GIL is implemented. When
- a thread releases the GIL and gil_drop_request is set, that thread
- ensures that another GIL-awaiting thread gets scheduled. It does so
- by waiting on a variable (gil_last_holder) controlled through another
- {mutex, condition} pair.
-
+ which ORs several conditions into one. Volatile booleans are
+ sufficient as inter-thread signalling means since Python is run
+ on cache-coherent architectures only.]
+
+ - A thread wanting to take the GIL will first let pass a given amount of
+ time (`interval` microseconds) before setting gil_drop_request. This
+ encourages a defined switching period, but doesn't enforce it since
+ opcodes can take an arbitrary time to execute.
+
+ The `interval` value is available for the user to read and modify
+ using the Python API `sys.{get,set}switchinterval()`.
+
+ - When a thread releases the GIL and gil_drop_request is set, that thread
+ ensures that another GIL-awaiting thread gets scheduled.
+ It does so by waiting on a condition variable (switch_cond) until
+ the value of gil_last_holder is changed to something else than its
+ own thread state pointer, indicating that another thread was able to
+ take the GIL.
+
+ This is meant to prohibit the latency-adverse behaviour on multi-core
+ machines where one thread would speculatively release the GIL, but still
+ run and end up being the first to re-acquire it, making the "timeslices"
+ much longer than expected.
+ (Note: this mechanism is enabled with FORCE_SWITCHING above)
*/
#ifndef _POSIX_THREADS
@@ -187,21 +198,24 @@
#endif /* _POSIX_THREADS, NT_THREADS */
-/* Whether the GIL is already taken (-1 if uninitialized) */
+/* Whether the GIL is already taken (-1 if uninitialized). This is volatile
+ because it can be read without any lock taken in ceval.c. */
static volatile int gil_locked = -1;
-/* Number of GIL switches since the beginning */
+/* Number of GIL switches since the beginning. */
static unsigned long gil_switch_number = 0;
-/* Last thread holding / having held the GIL */
+/* Last thread holding / having held the GIL. This helps us know whether
+ anyone else was scheduled after we dropped the GIL. */
static PyThreadState *gil_last_holder = NULL;
-/* This condition variable allows to put threads to sleep.
- In addition, the mutex also protects the above variables. */
+/* This condition variable allows one or several threads to wait until
+ the GIL is released. In addition, the mutex also protects the above
+ variables. */
static COND_T gil_cond;
static MUTEX_T gil_mutex;
#ifdef FORCE_SWITCHING
-/* This condition variable forces the GIL-releasing thread to wait for
- the scheduling of a GIL-awaiting thread, if any. */
+/* This condition variable helps the GIL-releasing thread wait for
+ a GIL-awaiting thread to be scheduled and take the GIL. */
static COND_T switch_cond;
static MUTEX_T switch_mutex;
#endif
More information about the Python-checkins
mailing list