mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-104530: Enable native Win32 condition variables by default (GH-104531)
This commit is contained in:
parent
d29f57f603
commit
b3f0b698da
6 changed files with 41 additions and 35 deletions
|
@ -35,14 +35,14 @@
|
||||||
#include <windows.h> // CRITICAL_SECTION
|
#include <windows.h> // CRITICAL_SECTION
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
/* non-emulated condition variables are provided for those that want
|
/* emulated condition variables are provided for those that want
|
||||||
* to target Windows Vista. Modify this macro to enable them.
|
* to target Windows XP or earlier. Modify this macro to enable them.
|
||||||
*/
|
*/
|
||||||
#ifndef _PY_EMULATED_WIN_CV
|
#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
|
#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
|
#if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
|
||||||
#undef _PY_EMULATED_WIN_CV
|
#undef _PY_EMULATED_WIN_CV
|
||||||
#define _PY_EMULATED_WIN_CV 1
|
#define _PY_EMULATED_WIN_CV 1
|
||||||
|
@ -77,7 +77,7 @@ typedef struct _PyCOND_T
|
||||||
|
|
||||||
#else /* !_PY_EMULATED_WIN_CV */
|
#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 */
|
/* SRWLOCK is faster and better than CriticalSection */
|
||||||
typedef SRWLOCK PyMUTEX_T;
|
typedef SRWLOCK PyMUTEX_T;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Use native Win32 condition variables.
|
|
@ -610,8 +610,16 @@ PyEval_SaveThread(void)
|
||||||
void
|
void
|
||||||
PyEval_RestoreThread(PyThreadState *tstate)
|
PyEval_RestoreThread(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
int err = GetLastError();
|
||||||
|
#endif
|
||||||
|
|
||||||
_Py_EnsureTstateNotNULL(tstate);
|
_Py_EnsureTstateNotNULL(tstate);
|
||||||
_PyThreadState_Attach(tstate);
|
_PyThreadState_Attach(tstate);
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
SetLastError(err);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -260,13 +260,13 @@ PyMUTEX_UNLOCK(PyMUTEX_T *cs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
PyCOND_INIT(PyCOND_T *cv)
|
PyCOND_INIT(PyCOND_T *cv)
|
||||||
{
|
{
|
||||||
InitializeConditionVariable(cv);
|
InitializeConditionVariable(cv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
PyCOND_FINI(PyCOND_T *cv)
|
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;
|
return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This implementation makes no distinction about timeouts. Signal
|
/* return 0 for success, 1 on timeout, -1 on error */
|
||||||
* 2 to indicate that we don't know.
|
|
||||||
*/
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
|
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)
|
Py_LOCAL_INLINE(int)
|
||||||
PyCOND_SIGNAL(PyCOND_T *cv)
|
PyCOND_SIGNAL(PyCOND_T *cv)
|
||||||
{
|
{
|
||||||
WakeConditionVariable(cv);
|
WakeConditionVariable(cv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
PyCOND_BROADCAST(PyCOND_T *cv)
|
PyCOND_BROADCAST(PyCOND_T *cv)
|
||||||
{
|
{
|
||||||
WakeAllConditionVariable(cv);
|
WakeAllConditionVariable(cv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2488,7 +2488,17 @@ PyGILState_Check(void)
|
||||||
return 0;
|
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
|
PyGILState_STATE
|
||||||
|
|
|
@ -444,16 +444,7 @@ PyThread_set_key_value(int key, void *value)
|
||||||
void *
|
void *
|
||||||
PyThread_get_key_value(int key)
|
PyThread_get_key_value(int key)
|
||||||
{
|
{
|
||||||
/* because TLS is used in the Py_END_ALLOW_THREAD macro,
|
return TlsGetValue(key);
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -525,14 +516,5 @@ void *
|
||||||
PyThread_tss_get(Py_tss_t *key)
|
PyThread_tss_get(Py_tss_t *key)
|
||||||
{
|
{
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
/* because TSS is used in the Py_END_ALLOW_THREAD macro,
|
return TlsGetValue(key->_key);
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue