[Python-checkins] r76216 - python/branches/py3k/Python/ceval_gil.h

antoine.pitrou python-checkins at python.org
Wed Nov 11 19:11:36 CET 2009


Author: antoine.pitrou
Date: Wed Nov 11 19:11:36 2009
New Revision: 76216
Log:
Our condition variable emulation under Windows is imperfect, which
seems to be the cause of the buildbot hangs. Try to fix it, and add
some comments.
Modified:
 python/branches/py3k/Python/ceval_gil.h
Modified: python/branches/py3k/Python/ceval_gil.h
==============================================================================
--- python/branches/py3k/Python/ceval_gil.h	(original)
+++ python/branches/py3k/Python/ceval_gil.h	Wed Nov 11 19:11:36 2009
@@ -153,8 +153,20 @@
 Py_FatalError("ReleaseMutex(" #mut ") failed"); };
 
 /* We emulate condition variables with events. It is sufficient here.
- (WaitForMultipleObjects() allows the event to be caught and the mutex
- to be taken atomically) */
+ WaitForMultipleObjects() allows the event to be caught and the mutex
+ to be taken atomically.
+ As for SignalObjectAndWait(), its semantics are unfortunately a bit
+ more foggy. Many sources on the Web define it as atomically releasing
+ the first object while starting to wait on the second, but MSDN states
+ it is *not* atomic...
+
+ In any case, the emulation here is tailored for our particular use case.
+ For example, we don't care how many threads are woken up when a condition
+ gets signalled. Generic emulations of the pthread_cond_* API using
+ Win32 functions can be found on the Web.
+ The following read can be edificating (or not):
+ http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
+*/
 #define COND_T HANDLE
 #define COND_INIT(cond) \
 /* auto-reset, non-signalled */ \
@@ -168,12 +180,9 @@
 Py_FatalError("SetEvent(" #cond ") failed"); };
 #define COND_WAIT(cond, mut) \
 { \
- DWORD r; \
- HANDLE objects[2] = { cond, mut }; \
- MUTEX_UNLOCK(mut); \
- r = WaitForMultipleObjects(2, objects, TRUE, INFINITE); \
- if (r != WAIT_OBJECT_0) \
- Py_FatalError("WaitForSingleObject(" #cond ") failed"); \
+ if (SignalObjectAndWait(mut, cond, INFINITE, FALSE) != WAIT_OBJECT_0) \
+ Py_FatalError("SignalObjectAndWait(" #mut ", " #cond") failed"); \
+ MUTEX_LOCK(mut); \
 }
 #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
 { \
@@ -257,7 +266,8 @@
 gil_locked = 0;
 COND_SIGNAL(gil_cond);
 #ifdef FORCE_SWITCHING
- COND_PREPARE(switch_cond);
+ if (gil_drop_request)
+ COND_PREPARE(switch_cond);
 #endif
 MUTEX_UNLOCK(gil_mutex);
 
@@ -266,6 +276,11 @@
 MUTEX_LOCK(switch_mutex);
 /* Not switched yet => wait */
 if (gil_last_holder == tstate)
+ /* NOTE: if COND_WAIT does not atomically start waiting when
+ releasing the mutex, another thread can run through, take
+ the GIL and drop it again, and reset the condition
+ (COND_PREPARE above) before we even had a chance to wait
+ for it. */
 COND_WAIT(switch_cond, switch_mutex);
 MUTEX_UNLOCK(switch_mutex);
 }


More information about the Python-checkins mailing list

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