Skip to content

Commit b3f0b69

Browse files
authored
gh-104530: Enable native Win32 condition variables by default (GH-104531)
1 parent d29f57f commit b3f0b69

File tree

6 files changed

+41
-35
lines changed

6 files changed

+41
-35
lines changed

Include/internal/pycore_condvar.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535
#include <windows.h> // CRITICAL_SECTION
3636

3737
/* options */
38-
/* non-emulated condition variables are provided for those that want
39-
* to target Windows Vista. Modify this macro to enable them.
38+
/* emulated condition variables are provided for those that want
39+
* to target Windows XP or earlier. Modify this macro to enable them.
4040
*/
4141
#ifndef _PY_EMULATED_WIN_CV
42-
#define _PY_EMULATED_WIN_CV 1 /* use emulated condition variables */
42+
#define _PY_EMULATED_WIN_CV 0 /* use non-emulated condition variables */
4343
#endif
4444

45-
/* fall back to emulation if not targeting Vista */
45+
/* fall back to emulation if targeting earlier than Vista */
4646
#if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
4747
#undef _PY_EMULATED_WIN_CV
4848
#define _PY_EMULATED_WIN_CV 1
@@ -77,7 +77,7 @@ typedef struct _PyCOND_T
7777

7878
#else /* !_PY_EMULATED_WIN_CV */
7979

80-
/* Use native Win7 primitives if build target is Win7 or higher */
80+
/* Use native Windows primitives if build target is Vista or higher */
8181

8282
/* SRWLOCK is faster and better than CriticalSection */
8383
typedef SRWLOCK PyMUTEX_T;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use native Win32 condition variables.

Python/ceval_gil.c

+8
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,16 @@ PyEval_SaveThread(void)
610610
void
611611
PyEval_RestoreThread(PyThreadState *tstate)
612612
{
613+
#ifdef MS_WINDOWS
614+
int err = GetLastError();
615+
#endif
616+
613617
_Py_EnsureTstateNotNULL(tstate);
614618
_PyThreadState_Attach(tstate);
619+
620+
#ifdef MS_WINDOWS
621+
SetLastError(err);
622+
#endif
615623
}
616624

617625

Python/condvar.h

+14-9
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,13 @@ PyMUTEX_UNLOCK(PyMUTEX_T *cs)
260260
return 0;
261261
}
262262

263-
264263
Py_LOCAL_INLINE(int)
265264
PyCOND_INIT(PyCOND_T *cv)
266265
{
267266
InitializeConditionVariable(cv);
268267
return 0;
269268
}
269+
270270
Py_LOCAL_INLINE(int)
271271
PyCOND_FINI(PyCOND_T *cv)
272272
{
@@ -279,27 +279,32 @@ PyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
279279
return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;
280280
}
281281

282-
/* This implementation makes no distinction about timeouts. Signal
283-
* 2 to indicate that we don't know.
284-
*/
282+
/* return 0 for success, 1 on timeout, -1 on error */
285283
Py_LOCAL_INLINE(int)
286284
PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
287285
{
288-
return SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0) ? 2 : -1;
286+
BOOL success = SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0);
287+
if (!success) {
288+
if (GetLastError() == ERROR_TIMEOUT) {
289+
return 1;
290+
}
291+
return -1;
292+
}
293+
return 0;
289294
}
290295

291296
Py_LOCAL_INLINE(int)
292297
PyCOND_SIGNAL(PyCOND_T *cv)
293298
{
294-
WakeConditionVariable(cv);
295-
return 0;
299+
WakeConditionVariable(cv);
300+
return 0;
296301
}
297302

298303
Py_LOCAL_INLINE(int)
299304
PyCOND_BROADCAST(PyCOND_T *cv)
300305
{
301-
WakeAllConditionVariable(cv);
302-
return 0;
306+
WakeAllConditionVariable(cv);
307+
return 0;
303308
}
304309

305310

Python/pystate.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -2488,7 +2488,17 @@ PyGILState_Check(void)
24882488
return 0;
24892489
}
24902490

2491-
return (tstate == gilstate_tss_get(runtime));
2491+
#ifdef MS_WINDOWS
2492+
int err = GetLastError();
2493+
#endif
2494+
2495+
PyThreadState *tcur = gilstate_tss_get(runtime);
2496+
2497+
#ifdef MS_WINDOWS
2498+
SetLastError(err);
2499+
#endif
2500+
2501+
return (tstate == tcur);
24922502
}
24932503

24942504
PyGILState_STATE

Python/thread_nt.h

+2-20
Original file line numberDiff line numberDiff line change
@@ -444,16 +444,7 @@ PyThread_set_key_value(int key, void *value)
444444
void *
445445
PyThread_get_key_value(int key)
446446
{
447-
/* because TLS is used in the Py_END_ALLOW_THREAD macro,
448-
* it is necessary to preserve the windows error state, because
449-
* it is assumed to be preserved across the call to the macro.
450-
* Ideally, the macro should be fixed, but it is simpler to
451-
* do it here.
452-
*/
453-
DWORD error = GetLastError();
454-
void *result = TlsGetValue(key);
455-
SetLastError(error);
456-
return result;
447+
return TlsGetValue(key);
457448
}
458449

459450
void
@@ -525,14 +516,5 @@ void *
525516
PyThread_tss_get(Py_tss_t *key)
526517
{
527518
assert(key != NULL);
528-
/* because TSS is used in the Py_END_ALLOW_THREAD macro,
529-
* it is necessary to preserve the windows error state, because
530-
* it is assumed to be preserved across the call to the macro.
531-
* Ideally, the macro should be fixed, but it is simpler to
532-
* do it here.
533-
*/
534-
DWORD error = GetLastError();
535-
void *result = TlsGetValue(key->_key);
536-
SetLastError(error);
537-
return result;
519+
return TlsGetValue(key->_key);
538520
}

0 commit comments

Comments
 (0)