mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
Fix problems in x64 build that were discovered by the testsuite:
- Reenable modules on x64 that had been disabled aeons ago for Itanium. - Cleared up confusion about compilers for 64 bit windows. There is only Itanium and x64. Added macros MS_WINI64 and MS_WINX64 for those rare cases where it matters, such as the disabling of modules above. - Set target platform (_WIN32_WINNT and WINVER) to 0x0501 (XP) for x64, and 0x0400 (NT 4.0) otherwise, which are the targeted minimum platforms. - Fixed thread_nt.h. The emulated InterlockedCompareExchange function didn´t work on x64, probaby due to the lack of a "volatile" specifier. Anyway, win95 is no longer a target platform. - Itertools module used wrong constant to check for overflow in count() - PyInt_AsSsize_t couldn't deal with attribute error when accessing the __long__ member. - PyLong_FromSsize_t() incorrectly specified that the operand were unsigned. With these changes, the x64 passes the testsuite, for those modules present.
This commit is contained in:
parent
170eee9d6a
commit
f030394de3
7 changed files with 36 additions and 73 deletions
|
@ -2073,9 +2073,9 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
count_next(countobject *lz)
|
count_next(countobject *lz)
|
||||||
{
|
{
|
||||||
if (lz->cnt == LONG_MAX) {
|
if (lz->cnt == PY_SSIZE_T_MAX) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"cannot count beyond LONG_MAX");
|
"cannot count beyond PY_SSIZE_T_MAX");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return PyInt_FromSsize_t(lz->cnt++);
|
return PyInt_FromSsize_t(lz->cnt++);
|
||||||
|
|
|
@ -263,7 +263,6 @@ extern int lstat(const char *, struct stat *);
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#endif
|
#endif
|
||||||
#include "osdefs.h"
|
#include "osdefs.h"
|
||||||
#define _WIN32_WINNT 0x0400 /* Needed for CryptoAPI on some systems */
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h> /* for ShellExecute() */
|
#include <shellapi.h> /* for ShellExecute() */
|
||||||
#define popen _popen
|
#define popen _popen
|
||||||
|
|
|
@ -215,6 +215,10 @@ PyInt_AsSsize_t(register PyObject *op)
|
||||||
|
|
||||||
if (nb->nb_long != 0) {
|
if (nb->nb_long != 0) {
|
||||||
io = (PyIntObject*) (*nb->nb_long) (op);
|
io = (PyIntObject*) (*nb->nb_long) (op);
|
||||||
|
if (io == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||||
|
PyErr_Clear();
|
||||||
|
io = (PyIntObject*) (*nb->nb_int) (op);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
io = (PyIntObject*) (*nb->nb_int) (op);
|
io = (PyIntObject*) (*nb->nb_int) (op);
|
||||||
}
|
}
|
||||||
|
|
|
@ -893,7 +893,7 @@ _PyLong_FromSsize_t(Py_ssize_t ival)
|
||||||
int one = 1;
|
int one = 1;
|
||||||
return _PyLong_FromByteArray(
|
return _PyLong_FromByteArray(
|
||||||
(unsigned char *)&bytes,
|
(unsigned char *)&bytes,
|
||||||
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0);
|
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new long int object from a C size_t. */
|
/* Create a new long int object from a C size_t. */
|
||||||
|
|
12
PC/config.c
12
PC/config.c
|
@ -6,21 +6,21 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
extern void initarray(void);
|
extern void initarray(void);
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
extern void initaudioop(void);
|
extern void initaudioop(void);
|
||||||
#endif
|
#endif
|
||||||
extern void initbinascii(void);
|
extern void initbinascii(void);
|
||||||
extern void initcmath(void);
|
extern void initcmath(void);
|
||||||
extern void initerrno(void);
|
extern void initerrno(void);
|
||||||
extern void initgc(void);
|
extern void initgc(void);
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
extern void initimageop(void);
|
extern void initimageop(void);
|
||||||
#endif
|
#endif
|
||||||
extern void initmath(void);
|
extern void initmath(void);
|
||||||
extern void init_md5(void);
|
extern void init_md5(void);
|
||||||
extern void initnt(void);
|
extern void initnt(void);
|
||||||
extern void initoperator(void);
|
extern void initoperator(void);
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
extern void initrgbimg(void);
|
extern void initrgbimg(void);
|
||||||
#endif
|
#endif
|
||||||
extern void initsignal(void);
|
extern void initsignal(void);
|
||||||
|
@ -80,7 +80,7 @@ struct _inittab _PyImport_Inittab[] = {
|
||||||
{"array", initarray},
|
{"array", initarray},
|
||||||
{"_ast", init_ast},
|
{"_ast", init_ast},
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
{"audioop", initaudioop},
|
{"audioop", initaudioop},
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -88,14 +88,14 @@ struct _inittab _PyImport_Inittab[] = {
|
||||||
{"cmath", initcmath},
|
{"cmath", initcmath},
|
||||||
{"errno", initerrno},
|
{"errno", initerrno},
|
||||||
{"gc", initgc},
|
{"gc", initgc},
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
{"imageop", initimageop},
|
{"imageop", initimageop},
|
||||||
#endif
|
#endif
|
||||||
{"math", initmath},
|
{"math", initmath},
|
||||||
{"_md5", init_md5},
|
{"_md5", init_md5},
|
||||||
{"nt", initnt}, /* Use the NT os functions, not posix */
|
{"nt", initnt}, /* Use the NT os functions, not posix */
|
||||||
{"operator", initoperator},
|
{"operator", initoperator},
|
||||||
#ifndef MS_WIN64
|
#ifndef MS_WINI64
|
||||||
{"rgbimg", initrgbimg},
|
{"rgbimg", initrgbimg},
|
||||||
#endif
|
#endif
|
||||||
{"signal", initsignal},
|
{"signal", initsignal},
|
||||||
|
|
|
@ -128,6 +128,8 @@ MS_CORE_DLL.
|
||||||
defined on Win32 *and* Win64. Win32 only code must therefore be
|
defined on Win32 *and* Win64. Win32 only code must therefore be
|
||||||
guarded as follows:
|
guarded as follows:
|
||||||
#if defined(MS_WIN32) && !defined(MS_WIN64)
|
#if defined(MS_WIN32) && !defined(MS_WIN64)
|
||||||
|
Some modules are disabled on Itanium processors, therefore we
|
||||||
|
have MS_WINI64 set for those targets, otherwise MS_WINX64
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#define MS_WIN64
|
#define MS_WIN64
|
||||||
|
@ -135,17 +137,28 @@ MS_CORE_DLL.
|
||||||
|
|
||||||
/* set the COMPILER */
|
/* set the COMPILER */
|
||||||
#ifdef MS_WIN64
|
#ifdef MS_WIN64
|
||||||
#ifdef _M_IX86
|
#if defined(_M_IA64)
|
||||||
#define COMPILER _Py_PASTE_VERSION("64 bit (Intel)")
|
|
||||||
#elif defined(_M_IA64)
|
|
||||||
#define COMPILER _Py_PASTE_VERSION("64 bit (Itanium)")
|
#define COMPILER _Py_PASTE_VERSION("64 bit (Itanium)")
|
||||||
#elif defined(_M_AMD64)
|
#define MS_WINI64
|
||||||
#define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)")
|
#elif defined(_M_X64)
|
||||||
|
#define COMPILER _Py_PASTE_VERSION("64 bit (x64)")
|
||||||
|
#define MS_WINX64
|
||||||
#else
|
#else
|
||||||
#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)")
|
#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)")
|
||||||
#endif
|
#endif
|
||||||
#endif /* MS_WIN64 */
|
#endif /* MS_WIN64 */
|
||||||
|
|
||||||
|
/* set the version macros for the windows headers */
|
||||||
|
#ifdef MS_WINX64
|
||||||
|
/* 64 bit only runs on XP or greater */
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#define WINVER 0x0501
|
||||||
|
#else
|
||||||
|
/* NT 4.0 or greater required otherwise */
|
||||||
|
#define _WIN32_WINNT 0x0400
|
||||||
|
#define WINVER 0x0400
|
||||||
|
#endif
|
||||||
|
|
||||||
/* _W64 is not defined for VC6 or eVC4 */
|
/* _W64 is not defined for VC6 or eVC4 */
|
||||||
#ifndef _W64
|
#ifndef _W64
|
||||||
#define _W64
|
#define _W64
|
||||||
|
|
|
@ -15,72 +15,16 @@ typedef struct NRMUTEX {
|
||||||
HANDLE hevent ;
|
HANDLE hevent ;
|
||||||
} NRMUTEX, *PNRMUTEX ;
|
} NRMUTEX, *PNRMUTEX ;
|
||||||
|
|
||||||
typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
|
|
||||||
|
|
||||||
/* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */
|
|
||||||
static PVOID WINAPI
|
|
||||||
interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand)
|
|
||||||
{
|
|
||||||
static LONG spinlock = 0 ;
|
|
||||||
PVOID result ;
|
|
||||||
DWORD dwSleep = 0;
|
|
||||||
|
|
||||||
/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
|
|
||||||
while(InterlockedExchange(&spinlock, 1))
|
|
||||||
{
|
|
||||||
// Using Sleep(0) can cause a priority inversion.
|
|
||||||
// Sleep(0) only yields the processor if there's
|
|
||||||
// another thread of the same priority that's
|
|
||||||
// ready to run. If a high-priority thread is
|
|
||||||
// trying to acquire the lock, which is held by
|
|
||||||
// a low-priority thread, then the low-priority
|
|
||||||
// thread may never get scheduled and hence never
|
|
||||||
// free the lock. NT attempts to avoid priority
|
|
||||||
// inversions by temporarily boosting the priority
|
|
||||||
// of low-priority runnable threads, but the problem
|
|
||||||
// can still occur if there's a medium-priority
|
|
||||||
// thread that's always runnable. If Sleep(1) is used,
|
|
||||||
// then the thread unconditionally yields the CPU. We
|
|
||||||
// only do this for the second and subsequent even
|
|
||||||
// iterations, since a millisecond is a long time to wait
|
|
||||||
// if the thread can be scheduled in again sooner
|
|
||||||
// (~100,000 instructions).
|
|
||||||
// Avoid priority inversion: 0, 1, 0, 1,...
|
|
||||||
Sleep(dwSleep);
|
|
||||||
dwSleep = !dwSleep;
|
|
||||||
}
|
|
||||||
result = *dest ;
|
|
||||||
if (result == comperand)
|
|
||||||
*dest = exc ;
|
|
||||||
/* Release spinlock */
|
|
||||||
spinlock = 0 ;
|
|
||||||
return result ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
static interlocked_cmp_xchg_t *ixchg;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
InitializeNonRecursiveMutex(PNRMUTEX mutex)
|
InitializeNonRecursiveMutex(PNRMUTEX mutex)
|
||||||
{
|
{
|
||||||
if (!ixchg)
|
|
||||||
{
|
|
||||||
/* Sorely, Win95 has no InterlockedCompareExchange API (Win98 has), so we have to use emulation */
|
|
||||||
HANDLE kernel = GetModuleHandle("kernel32.dll") ;
|
|
||||||
if (!kernel || (ixchg = (interlocked_cmp_xchg_t *)GetProcAddress(kernel, "InterlockedCompareExchange")) == NULL)
|
|
||||||
ixchg = interlocked_cmp_xchg ;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
|
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
|
||||||
mutex->thread_id = 0 ;
|
mutex->thread_id = 0 ;
|
||||||
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
|
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
|
||||||
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
|
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef InterlockedCompareExchange
|
|
||||||
#undef InterlockedCompareExchange
|
|
||||||
#endif
|
|
||||||
#define InterlockedCompareExchange(dest,exchange,comperand) (ixchg((dest), (exchange), (comperand)))
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
DeleteNonRecursiveMutex(PNRMUTEX mutex)
|
DeleteNonRecursiveMutex(PNRMUTEX mutex)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +42,7 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait)
|
||||||
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
|
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
|
||||||
if (!wait)
|
if (!wait)
|
||||||
{
|
{
|
||||||
if (InterlockedCompareExchange((PVOID *)&mutex->owned, (PVOID)0, (PVOID)-1) != (PVOID)-1)
|
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
|
||||||
return WAIT_TIMEOUT ;
|
return WAIT_TIMEOUT ;
|
||||||
ret = WAIT_OBJECT_0 ;
|
ret = WAIT_OBJECT_0 ;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +140,10 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||||
if (obj.done == NULL)
|
if (obj.done == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rv = _beginthread(bootstrap, _pythread_stacksize, &obj);
|
rv = _beginthread(bootstrap,
|
||||||
|
Py_SAFE_DOWNCAST(_pythread_stacksize,
|
||||||
|
Py_ssize_t, int),
|
||||||
|
&obj);
|
||||||
if (rv == (Py_uintptr_t)-1) {
|
if (rv == (Py_uintptr_t)-1) {
|
||||||
/* I've seen errno == EAGAIN here, which means "there are
|
/* I've seen errno == EAGAIN here, which means "there are
|
||||||
* too many threads".
|
* too many threads".
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue