]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-104530: Enable native Win32 condition variables by default (GH-104531)
authorAndrew Rogers <32688592+adr26@users.noreply.github.com>
Fri, 2 Feb 2024 13:50:51 +0000 (13:50 +0000)
committerGitHub <noreply@github.com>
Fri, 2 Feb 2024 13:50:51 +0000 (13:50 +0000)
Include/internal/pycore_condvar.h
Misc/NEWS.d/next/Core and Builtins/2023-05-16-06-52-34.gh-issue-104530.mJnA0W.rst [new file with mode: 0644]
Python/ceval_gil.c
Python/condvar.h
Python/pystate.c
Python/thread_nt.h

index 34c21aaad43197b439af6fe419eb17397042b46d..ee9533484e80488cb55e921c197fba6147fb8176 100644 (file)
 #include <windows.h>              // CRITICAL_SECTION
 
 /* options */
-/* non-emulated condition variables are provided for those that want
- * to target Windows Vista.  Modify this macro to enable them.
+/* emulated condition variables are provided for those that want
+ * to target Windows XP or earlier. Modify this macro to enable them.
  */
 #ifndef _PY_EMULATED_WIN_CV
-#define _PY_EMULATED_WIN_CV 1  /* use emulated condition variables */
+#define _PY_EMULATED_WIN_CV 0  /* use non-emulated condition variables */
 #endif
 
-/* fall back to emulation if not targeting Vista */
+/* fall back to emulation if targeting earlier than Vista */
 #if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
 #undef _PY_EMULATED_WIN_CV
 #define _PY_EMULATED_WIN_CV 1
@@ -77,7 +77,7 @@ typedef struct _PyCOND_T
 
 #else /* !_PY_EMULATED_WIN_CV */
 
-/* Use native Win7 primitives if build target is Win7 or higher */
+/* Use native Windows primitives if build target is Vista or higher */
 
 /* SRWLOCK is faster and better than CriticalSection */
 typedef SRWLOCK PyMUTEX_T;
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-16-06-52-34.gh-issue-104530.mJnA0W.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-16-06-52-34.gh-issue-104530.mJnA0W.rst
new file mode 100644 (file)
index 0000000..8643a25
--- /dev/null
@@ -0,0 +1 @@
+Use native Win32 condition variables.
index f3b169241535f379c8d7bd217dc84834fbc41ed1..ad90359318761a5ab01b7bf38215f59f0f7648e8 100644 (file)
@@ -610,8 +610,16 @@ PyEval_SaveThread(void)
 void
 PyEval_RestoreThread(PyThreadState *tstate)
 {
+#ifdef MS_WINDOWS
+    int err = GetLastError();
+#endif
+
     _Py_EnsureTstateNotNULL(tstate);
     _PyThreadState_Attach(tstate);
+
+#ifdef MS_WINDOWS
+    SetLastError(err);
+#endif
 }
 
 
index d54db94f2c871d49bdf362b19d9c912ad893b0eb..dcabed6d55928cec813eb09b9e5a299234862481 100644 (file)
@@ -260,13 +260,13 @@ PyMUTEX_UNLOCK(PyMUTEX_T *cs)
     return 0;
 }
 
-
 Py_LOCAL_INLINE(int)
 PyCOND_INIT(PyCOND_T *cv)
 {
     InitializeConditionVariable(cv);
     return 0;
 }
+
 Py_LOCAL_INLINE(int)
 PyCOND_FINI(PyCOND_T *cv)
 {
@@ -279,27 +279,32 @@ PyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
     return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;
 }
 
-/* This implementation makes no distinction about timeouts.  Signal
- * 2 to indicate that we don't know.
- */
+/* return 0 for success, 1 on timeout, -1 on error */
 Py_LOCAL_INLINE(int)
 PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
 {
-    return SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0) ? 2 : -1;
+    BOOL success = SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0);
+    if (!success) {
+        if (GetLastError() == ERROR_TIMEOUT) {
+            return 1;
+        }
+        return -1;
+    }
+    return 0;
 }
 
 Py_LOCAL_INLINE(int)
 PyCOND_SIGNAL(PyCOND_T *cv)
 {
-     WakeConditionVariable(cv);
-     return 0;
+    WakeConditionVariable(cv);
+    return 0;
 }
 
 Py_LOCAL_INLINE(int)
 PyCOND_BROADCAST(PyCOND_T *cv)
 {
-     WakeAllConditionVariable(cv);
-     return 0;
+    WakeAllConditionVariable(cv);
+    return 0;
 }
 
 
index 27b6d0573ade3b3d9a9a3e638908e12e8c701381..7836c172bbfb61846a26efa24407e3d5afc265c7 100644 (file)
@@ -2488,7 +2488,17 @@ PyGILState_Check(void)
         return 0;
     }
 
-    return (tstate == gilstate_tss_get(runtime));
+#ifdef MS_WINDOWS
+    int err = GetLastError();
+#endif
+
+    PyThreadState *tcur = gilstate_tss_get(runtime);
+
+#ifdef MS_WINDOWS
+    SetLastError(err);
+#endif
+
+    return (tstate == tcur);
 }
 
 PyGILState_STATE
index 14b9cddc24c0ec344cfb5890e0a53c45cf1a4668..044e9fa111e979756192e028484102f8c16e38b2 100644 (file)
@@ -444,16 +444,7 @@ PyThread_set_key_value(int key, void *value)
 void *
 PyThread_get_key_value(int key)
 {
-    /* because TLS is used in the Py_END_ALLOW_THREAD macro,
-     * it is necessary to preserve the windows error state, because
-     * it is assumed to be preserved across the call to the macro.
-     * Ideally, the macro should be fixed, but it is simpler to
-     * do it here.
-     */
-    DWORD error = GetLastError();
-    void *result = TlsGetValue(key);
-    SetLastError(error);
-    return result;
+    return TlsGetValue(key);
 }
 
 void
@@ -525,14 +516,5 @@ void *
 PyThread_tss_get(Py_tss_t *key)
 {
     assert(key != NULL);
-    /* because TSS is used in the Py_END_ALLOW_THREAD macro,
-     * it is necessary to preserve the windows error state, because
-     * it is assumed to be preserved across the call to the macro.
-     * Ideally, the macro should be fixed, but it is simpler to
-     * do it here.
-     */
-    DWORD error = GetLastError();
-    void *result = TlsGetValue(key->_key);
-    SetLastError(error);
-    return result;
+    return TlsGetValue(key->_key);
 }