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.
parent 170eee9d
...@@ -2073,9 +2073,9 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -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 *); ...@@ -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) ...@@ -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) ...@@ -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. */
......
...@@ -6,21 +6,21 @@ ...@@ -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[] = { ...@@ -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[] = { ...@@ -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. ...@@ -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. ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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".
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment