Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] bpo-32592: Drop support for Windows Vista #5231

Closed
wants to merge 5 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions Doc/library/time.rst
Original file line number Diff line number Diff line change
@@ -293,14 +293,6 @@ Functions
The reference point of the returned value is undefined, so that only the
difference between the results of consecutive calls is valid.

On Windows versions older than Vista, :func:`monotonic` detects
:c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 days).
It increases an internal epoch (reference time) by 2\ :sup:`32` each time
that an overflow is detected. The epoch is stored in the process-local state
and so the value of :func:`monotonic` may be different in two Python
processes running for more than 49 days. On more recent versions of Windows
and on other operating systems, :func:`monotonic` is system-wide.

.. versionadded:: 3.3
.. versionchanged:: 3.5
The function is now always available.
3 changes: 2 additions & 1 deletion Doc/using/windows.rst
Original file line number Diff line number Diff line change
@@ -29,7 +29,8 @@ Supported Versions

As specified in :pep:`11`, a Python release only supports a Windows platform
while Microsoft considers the platform under extended support. This means that
Python |version| supports Windows Vista and newer. If you require Windows XP
Python |version| supports Windows 7 and newer. If you require Windows Vista
support then please install Python 3.6. If you require Windows XP
support then please install Python 3.4.

Installation Steps
54 changes: 1 addition & 53 deletions Include/internal/condvar.h
Original file line number Diff line number Diff line change
@@ -22,70 +22,18 @@
#define PyCOND_T pthread_cond_t

#elif defined(NT_THREADS)
/*
* Windows (XP, 2003 server and later, as well as (hopefully) CE) support
*
* Emulated condition variables ones that work with XP and later, plus
* example native support on VISTA and onwards.
*/
/* Windows support: use native Win7 primitives */
#define Py_HAVE_CONDVAR

/* include windows if it hasn't been done before */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* options */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could change the comment before #define Py_HAVE_CONDVAR ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in fact, should we remove all the references to Vista when we drop the support of Vista ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the comment.

/* non-emulated condition variables are provided for those that want
* to target Windows Vista. Modify this macro to enable them.
*/
#ifndef _PY_EMULATED_WIN_CV
#define _PY_EMULATED_WIN_CV 1 /* use emulated condition variables */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't removing this a mistake? I think the SRWLOCK version was tried in another issue that was abandoned.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, this code seems to sensitive and my change may conflict with https://bugs.python.org/issue29871 so I reverted this change and will open a new dedicated PR.

#endif

/* fall back to emulation if not targeting Vista */
#if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
#undef _PY_EMULATED_WIN_CV
#define _PY_EMULATED_WIN_CV 1
#endif

#if _PY_EMULATED_WIN_CV

typedef CRITICAL_SECTION PyMUTEX_T;

/* The ConditionVariable object. From XP onwards it is easily emulated
with a Semaphore.
Semaphores are available on Windows XP (2003 server) and later.
We use a Semaphore rather than an auto-reset event, because although
an auto-resent event might appear to solve the lost-wakeup bug (race
condition between releasing the outer lock and waiting) because it
maintains state even though a wait hasn't happened, there is still
a lost wakeup problem if more than one thread are interrupted in the
critical place. A semaphore solves that, because its state is
counted, not Boolean.
Because it is ok to signal a condition variable with no one
waiting, we need to keep track of the number of
waiting threads. Otherwise, the semaphore's state could rise
without bound. This also helps reduce the number of "spurious wakeups"
that would otherwise happen.
*/

typedef struct _PyCOND_T
{
HANDLE sem;
int waiting; /* to allow PyCOND_SIGNAL to be a no-op */
} PyCOND_T;

#else /* !_PY_EMULATED_WIN_CV */

/* Use native Win7 primitives if build target is Win7 or higher */

/* SRWLOCK is faster and better than CriticalSection */
typedef SRWLOCK PyMUTEX_T;

typedef CONDITION_VARIABLE PyCOND_T;

#endif /* _PY_EMULATED_WIN_CV */

#endif /* _POSIX_THREADS, NT_THREADS */

#endif /* Py_INTERNAL_CONDVAR_H */
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Drop support for Windows Vista. Windows Vista extended support ended in
April 2017. As stated in :pep:`11`, Python 3.7 drops support for Windows
Vista and now requires Windows 7 or newer.
17 changes: 1 addition & 16 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
@@ -11153,22 +11153,7 @@ os_cpu_count_impl(PyObject *module)
{
int ncpu = 0;
#ifdef MS_WINDOWS
/* Vista is supported and the GetMaximumProcessorCount API is Win7+
Need to fallback to Vista behavior if this call isn't present */
HINSTANCE hKernel32;
hKernel32 = GetModuleHandleW(L"KERNEL32");

static DWORD(CALLBACK *_GetMaximumProcessorCount)(WORD) = NULL;
*(FARPROC*)&_GetMaximumProcessorCount = GetProcAddress(hKernel32,
"GetMaximumProcessorCount");
if (_GetMaximumProcessorCount != NULL) {
ncpu = _GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
}
else {
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
ncpu = sysinfo.dwNumberOfProcessors;
}
ncpu = GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
#elif defined(__hpux)
ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
4 changes: 2 additions & 2 deletions PC/pyconfig.h
Original file line number Diff line number Diff line change
@@ -132,8 +132,8 @@ WIN32 is still required for the locale module.
#endif /* MS_WIN64 */

/* set the version macros for the windows headers */
/* Python 3.5+ requires Windows Vista or greater */
#define Py_WINVER 0x0600 /* _WIN32_WINNT_VISTA */
/* Python 3.7+ requires Windows 7 or greater */
#define Py_WINVER 0x0601 /* _WIN32_WINNT_WIN7 */
#define Py_NTDDI NTDDI_VISTA

/* We only set these values when building Python - we don't want to force
6 changes: 3 additions & 3 deletions PC/pyshellext.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Support back to Vista
#define _WIN32_WINNT _WIN32_WINNT_VISTA
// Support back to Windows 7
#define _WIN32_WINNT _WIN32_WINNT_WIN7
#include <sdkddkver.h>

// Use WRL to define a classic COM class
@@ -602,4 +602,4 @@ STDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) {
DisableThreadLibraryCalls(hinst);
}
return TRUE;
}
}
2 changes: 1 addition & 1 deletion PCbuild/readme.txt
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ Building Python using Microsoft Visual C++
------------------------------------------

This directory is used to build CPython for Microsoft Windows NT version
6.0 or higher (Windows Vista, Windows Server 2008, or later) on 32 and 64
6.1 or higher (Windows 7 or later) on 32 and 64
bit platforms. Using this directory requires an installation of
Microsoft Visual Studio 2017 (MSVC 14.1) with the *Python workload* and
its optional *Python native development* component selected. (For
153 changes: 0 additions & 153 deletions Python/condvar.h
Original file line number Diff line number Diff line change
@@ -97,156 +97,6 @@ PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
}

#elif defined(NT_THREADS)
/*
* Windows (XP, 2003 server and later, as well as (hopefully) CE) support
*
* Emulated condition variables ones that work with XP and later, plus
* example native support on VISTA and onwards.
*/

#if _PY_EMULATED_WIN_CV
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://bugs.python.org/issue29871 before pulling this code out - our alternate code isn't 100% correct yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I can revert this change and propose it in https://bugs.python.org/issue29871.

My change should have no effect on Windows 7 and newer. Why do you prefer to keep the unused emulation code (until bpo-29871 is fixed)?


/* The mutex is a CriticalSection object and
The condition variables is emulated with the help of a semaphore.

This implementation still has the problem that the threads woken
with a "signal" aren't necessarily those that are already
waiting. It corresponds to listing 2 in:
http://birrell.org/andrew/papers/ImplementingCVs.pdf

Generic emulations of the pthread_cond_* API using
earlier Win32 functions can be found on the Web.
The following read can be give background information to these issues,
but the implementations are all broken in some way.
http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/

Py_LOCAL_INLINE(int)
PyMUTEX_INIT(PyMUTEX_T *cs)
{
InitializeCriticalSection(cs);
return 0;
}

Py_LOCAL_INLINE(int)
PyMUTEX_FINI(PyMUTEX_T *cs)
{
DeleteCriticalSection(cs);
return 0;
}

Py_LOCAL_INLINE(int)
PyMUTEX_LOCK(PyMUTEX_T *cs)
{
EnterCriticalSection(cs);
return 0;
}

Py_LOCAL_INLINE(int)
PyMUTEX_UNLOCK(PyMUTEX_T *cs)
{
LeaveCriticalSection(cs);
return 0;
}


Py_LOCAL_INLINE(int)
PyCOND_INIT(PyCOND_T *cv)
{
/* A semaphore with a "large" max value, The positive value
* is only needed to catch those "lost wakeup" events and
* race conditions when a timed wait elapses.
*/
cv->sem = CreateSemaphore(NULL, 0, 100000, NULL);
if (cv->sem==NULL)
return -1;
cv->waiting = 0;
return 0;
}

Py_LOCAL_INLINE(int)
PyCOND_FINI(PyCOND_T *cv)
{
return CloseHandle(cv->sem) ? 0 : -1;
}

/* this implementation can detect a timeout. Returns 1 on timeout,
* 0 otherwise (and -1 on error)
*/
Py_LOCAL_INLINE(int)
_PyCOND_WAIT_MS(PyCOND_T *cv, PyMUTEX_T *cs, DWORD ms)
{
DWORD wait;
cv->waiting++;
PyMUTEX_UNLOCK(cs);
/* "lost wakeup bug" would occur if the caller were interrupted here,
* but we are safe because we are using a semaphore which has an internal
* count.
*/
wait = WaitForSingleObjectEx(cv->sem, ms, FALSE);
PyMUTEX_LOCK(cs);
if (wait != WAIT_OBJECT_0)
--cv->waiting;
/* Here we have a benign race condition with PyCOND_SIGNAL.
* When failure occurs or timeout, it is possible that
* PyCOND_SIGNAL also decrements this value
* and signals releases the mutex. This is benign because it
* just means an extra spurious wakeup for a waiting thread.
* ('waiting' corresponds to the semaphore's "negative" count and
* we may end up with e.g. (waiting == -1 && sem.count == 1). When
* a new thread comes along, it will pass right throuhgh, having
* adjusted it to (waiting == 0 && sem.count == 0).
*/

if (wait == WAIT_FAILED)
return -1;
/* return 0 on success, 1 on timeout */
return wait != WAIT_OBJECT_0;
}

Py_LOCAL_INLINE(int)
PyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
{
int result = _PyCOND_WAIT_MS(cv, cs, INFINITE);
return result >= 0 ? 0 : result;
}

Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
{
return _PyCOND_WAIT_MS(cv, cs, (DWORD)(us/1000));
}

Py_LOCAL_INLINE(int)
PyCOND_SIGNAL(PyCOND_T *cv)
{
/* this test allows PyCOND_SIGNAL to be a no-op unless required
* to wake someone up, thus preventing an unbounded increase of
* the semaphore's internal counter.
*/
if (cv->waiting > 0) {
/* notifying thread decreases the cv->waiting count so that
* a delay between notify and actual wakeup of the target thread
* doesn't cause a number of extra ReleaseSemaphore calls.
*/
cv->waiting--;
return ReleaseSemaphore(cv->sem, 1, NULL) ? 0 : -1;
}
return 0;
}

Py_LOCAL_INLINE(int)
PyCOND_BROADCAST(PyCOND_T *cv)
{
int waiting = cv->waiting;
if (waiting > 0) {
cv->waiting = 0;
return ReleaseSemaphore(cv->sem, waiting, NULL) ? 0 : -1;
}
return 0;
}

#else /* !_PY_EMULATED_WIN_CV */

Py_LOCAL_INLINE(int)
PyMUTEX_INIT(PyMUTEX_T *cs)
@@ -317,9 +167,6 @@ PyCOND_BROADCAST(PyCOND_T *cv)
return 0;
}


#endif /* _PY_EMULATED_WIN_CV */

#endif /* _POSIX_THREADS, NT_THREADS */

#endif /* _CONDVAR_IMPL_H_ */