summaryrefslogtreecommitdiffstats
path: root/Python/thread_nt.h
diff options
context:
space:
mode:
authorKristján Valur Jónsson <kristjan@ccpgames.com>2012-06-18 20:30:44 (GMT)
committerKristján Valur Jónsson <kristjan@ccpgames.com>2012-06-18 20:30:44 (GMT)
commite75ff35af2b6c85d48c68b95f295aeac7396b162 (patch)
tree2a416019134e19290cf88c9b43de3cd9a91791aa /Python/thread_nt.h
parent633c4d919978bbccae239a69d99180b6d2afcd40 (diff)
downloadcpython-e75ff35af2b6c85d48c68b95f295aeac7396b162.zip
cpython-e75ff35af2b6c85d48c68b95f295aeac7396b162.tar.gz
cpython-e75ff35af2b6c85d48c68b95f295aeac7396b162.tar.bz2
Issue #15038: Optimize python Locks on Windows
Extract cross-platform condition variable support into a separate file and provide user-mode non-recursive locks for Windows.
Diffstat (limited to 'Python/thread_nt.h')
-rw-r--r--Python/thread_nt.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index d1bb0e5..938bf1e 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -9,6 +9,109 @@
#include <process.h>
#endif
+/* options */
+#ifndef _PY_USE_CV_LOCKS
+#define _PY_USE_CV_LOCKS 1 /* use locks based on cond vars */
+#endif
+
+/* Now, define a non-recursive mutex using either condition variables
+ * and critical sections (fast) or using operating system mutexes
+ * (slow)
+ */
+
+#if _PY_USE_CV_LOCKS
+
+#include "condvar.h"
+
+typedef struct _NRMUTEX
+{
+ PyMUTEX_T cs;
+ PyCOND_T cv;
+ int locked;
+} NRMUTEX;
+typedef NRMUTEX *PNRMUTEX;
+
+PNRMUTEX
+AllocNonRecursiveMutex()
+{
+ PNRMUTEX m = (PNRMUTEX)malloc(sizeof(NRMUTEX));
+ if (!m)
+ return NULL;
+ if (PyCOND_INIT(&m->cv))
+ goto fail;
+ if (PyMUTEX_INIT(&m->cs)) {
+ PyCOND_FINI(&m->cv);
+ goto fail;
+ }
+ m->locked = 0;
+ return m;
+fail:
+ free(m);
+ return NULL;
+}
+
+VOID
+FreeNonRecursiveMutex(PNRMUTEX mutex)
+{
+ if (mutex) {
+ PyCOND_FINI(&mutex->cv);
+ PyMUTEX_FINI(&mutex->cs);
+ free(mutex);
+ }
+}
+
+DWORD
+EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
+{
+ DWORD result = WAIT_OBJECT_0;
+ if (PyMUTEX_LOCK(&mutex->cs))
+ return WAIT_FAILED;
+ if (milliseconds == INFINITE) {
+ while (mutex->locked) {
+ if (PyCOND_WAIT(&mutex->cv, &mutex->cs)) {
+ result = WAIT_FAILED;
+ break;
+ }
+ }
+ } else if (milliseconds != 0) {
+ /* wait at least until the target */
+ DWORD now, target = GetTickCount() + milliseconds;
+ while (mutex->locked) {
+ if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, milliseconds*1000) < 0) {
+ result = WAIT_FAILED;
+ break;
+ }
+ now = GetTickCount();
+ if (target <= now)
+ break;
+ milliseconds = target-now;
+ }
+ }
+ if (!mutex->locked) {
+ mutex->locked = 1;
+ result = WAIT_OBJECT_0;
+ } else if (result == WAIT_OBJECT_0)
+ result = WAIT_TIMEOUT;
+ /* else, it is WAIT_FAILED */
+ PyMUTEX_UNLOCK(&mutex->cs); /* must ignore result here */
+ return result;
+}
+
+BOOL
+LeaveNonRecursiveMutex(PNRMUTEX mutex)
+{
+ BOOL result;
+ if (PyMUTEX_LOCK(&mutex->cs))
+ return FALSE;
+ mutex->locked = 0;
+ result = PyCOND_SIGNAL(&mutex->cv);
+ result &= PyMUTEX_UNLOCK(&mutex->cs);
+ return result;
+}
+
+#else /* if ! _PY_USE_CV_LOCKS */
+
+/* NR-locks based on a kernel mutex */
#define PNRMUTEX HANDLE
PNRMUTEX
@@ -35,6 +138,7 @@ LeaveNonRecursiveMutex(PNRMUTEX mutex)
{
return ReleaseSemaphore(mutex, 1, NULL);
}
+#endif /* _PY_USE_CV_LOCKS */
long PyThread_get_thread_ident(void);