[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

AltStyle によって変換されたページ (->オリジナル) /