diff --git a/include/thread.h b/include/thread.h index 6dd0c25737b..882b1e1df64 100644 --- a/include/thread.h +++ b/include/thread.h @@ -132,7 +132,4 @@ extern int SYSDEPS_SpawnThread( TEB *teb ); extern void SYSDEPS_SetCurThread( TEB *teb ); extern void SYSDEPS_ExitThread(void); -#define SetLastError(err) ((void)(NtCurrentTeb()->last_error = (err))) -#define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->tid) - #endif /* __WINE_THREAD_H */ diff --git a/include/winbase.h b/include/winbase.h index 5cc91ffd44e..d66b5c6246c 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1356,11 +1356,6 @@ BOOL WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE); BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR); BOOL WINAPI IsValidSid(PSID); BOOL WINAPI ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL); -PVOID WINAPI InterlockedCompareExchange(PVOID*,PVOID,PVOID); -LONG WINAPI InterlockedDecrement(LPLONG); -LONG WINAPI InterlockedExchange(LPLONG,LONG); -LONG WINAPI InterlockedExchangeAdd(PLONG,LONG); -LONG WINAPI InterlockedIncrement(LPLONG); BOOL WINAPI IsDBCSLeadByteEx(UINT,BYTE); BOOL WINAPI IsProcessorFeaturePresent(DWORD); BOOL WINAPI IsValidLocale(DWORD,DWORD); @@ -1509,7 +1504,6 @@ BOOL WINAPI WriteConsoleA(HANDLE,LPCVOID,DWORD,LPDWORD,LPVOID); BOOL WINAPI WriteConsoleW(HANDLE,LPCVOID,DWORD,LPDWORD,LPVOID); #define WriteConsole WINELIB_NAME_AW(WriteConsole) BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED); -DWORD WINAPI GetLastError(void); LANGID WINAPI GetSystemDefaultLangID(void); LCID WINAPI GetSystemDefaultLCID(void); LANGID WINAPI GetUserDefaultLangID(void); @@ -1763,13 +1757,74 @@ INT WINAPI lstrcmpiW(LPCWSTR,LPCWSTR); #define ZeroMemory RtlZeroMemory #define CopyMemory RtlCopyMemory -/* the following may be macros when compiling Wine */ -#ifndef SetLastError -VOID WINAPI SetLastError(DWORD); -#endif -#ifndef GetCurrentThreadId -DWORD WINAPI GetCurrentThreadId(void); -#endif +/* a few optimizations for i386/gcc */ + +#if defined(__i386__) && defined(__GNUC__) + +static inline PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare ) +{ + PVOID ret; + __asm__ __volatile__( "lock; cmpxchgl %2,(%1)" + : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); + return ret; +} + +static inline LONG WINAPI InterlockedExchange( PLONG dest, LONG val ) +{ + LONG ret; + __asm__ __volatile__( "lock; xchgl %0,(%1)" + : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); + return ret; +} + +static inline LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ) +{ + LONG ret; + __asm__ __volatile__( "lock; xaddl %0,(%1)" + : "=r" (ret) : "r" (dest), "0" (incr) : "memory" ); + return ret; +} + +static inline LONG WINAPI InterlockedIncrement( PLONG dest ) +{ + return InterlockedExchangeAdd( dest, 1 ) + 1; +} + +static inline LONG WINAPI InterlockedDecrement( PLONG dest ) +{ + return InterlockedExchangeAdd( dest, -1 ) - 1; +} + +static inline DWORD WINAPI GetLastError(void) +{ + DWORD ret; + __asm__ __volatile__( ".byte 0x64\n\tmovl 0x60,%0" : "=r" (ret) ); + return ret; +} + +static inline DWORD WINAPI GetCurrentThreadId(void) +{ + DWORD ret; + __asm__ __volatile__( ".byte 0x64\n\tmovl 0x24,%0" : "=r" (ret) ); + return ret; +} + +static inline void WINAPI SetLastError( DWORD err ) +{ + __asm__ __volatile__( ".byte 0x64\n\tmovl %0,0x60" : : "r" (err) : "memory" ); +} + +#else /* __i386__ && __GNUC__ */ +DWORD WINAPI GetCurrentThreadId(void); +DWORD WINAPI GetLastError(void); +PVOID WINAPI InterlockedCompareExchange(PVOID*,PVOID,PVOID); +LONG WINAPI InterlockedDecrement(PLONG); +LONG WINAPI InterlockedExchange(PLONG,LONG); +LONG WINAPI InterlockedExchangeAdd(PLONG,LONG); +LONG WINAPI InterlockedIncrement(PLONG); +VOID WINAPI SetLastError(DWORD); +#endif /* __i386__ && __GNUC__ */ + #ifdef __cplusplus } diff --git a/scheduler/critsection.c b/scheduler/critsection.c index 0c8d6cc3291..c5560fa5a37 100644 --- a/scheduler/critsection.c +++ b/scheduler/critsection.c @@ -196,3 +196,46 @@ void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit ) } } +#ifdef __i386__ + +/* PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare ); */ +__ASM_GLOBAL_FUNC(InterlockedCompareExchange, + "movl 12(%esp),%eax\n\t" + "movl 8(%esp),%ecx\n\t" + "movl 4(%esp),%edx\n\t" + "lock; cmpxchgl %ecx,(%edx)\n\t" + "ret $12"); + +/* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */ +__ASM_GLOBAL_FUNC(InterlockedExchange, + "movl 8(%esp),%eax\n\t" + "movl 4(%esp),%edx\n\t" + "lock; xchgl %eax,(%edx)\n\t" + "ret $8"); + +/* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */ +__ASM_GLOBAL_FUNC(InterlockedExchangeAdd, + "movl 8(%esp),%eax\n\t" + "movl 4(%esp),%edx\n\t" + "lock; xaddl %eax,(%edx)\n\t" + "ret $8"); + +/* LONG WINAPI InterlockedIncrement( PLONG dest ); */ +__ASM_GLOBAL_FUNC(InterlockedIncrement, + "movl 4(%esp),%edx\n\t" + "movl $1,%eax\n\t" + "lock; xaddl %eax,(%edx)\n\t" + "incl %eax\n\t" + "ret $4"); + +/* LONG WINAPI InterlockedDecrement( PLONG dest ); */ +__ASM_GLOBAL_FUNC(InterlockedDecrement, + "movl 4(%esp),%edx\n\t" + "movl $-1,%eax\n\t" + "lock; xaddl %eax,(%edx)\n\t" + "decl %eax\n\t" + "ret $4"); + +#else /* __i386__ */ +#error You must implement the Interlocked* functions for your CPU +#endif /* __i386__ */ diff --git a/scheduler/thread.c b/scheduler/thread.c index 5a725e9f95c..17310beca75 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -356,18 +356,6 @@ HANDLE WINAPI GetCurrentThread(void) } -/********************************************************************** - * GetLastError [KERNEL.148] [KERNEL32.227] Returns last-error code. - * - * RETURNS - * Calling thread's last error code value. - */ -DWORD WINAPI GetLastError(void) -{ - return NtCurrentTeb()->last_error; -} - - /********************************************************************** * SetLastErrorEx [USER32.485] Sets the last-error code. * @@ -829,27 +817,45 @@ BOOL WINAPI SetThreadLocale( } +#ifdef __i386__ + +/* void WINAPI SetLastError( DWORD error ); */ +__ASM_GLOBAL_FUNC( SetLastError, + "movl 4(%esp),%eax\n\t" + ".byte 0x64\n\t" + "movl %eax,0x60\n\t" + "ret $4" ); + +/* DWORD WINAPI GetLastError(void); */ +__ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x60,%eax\n\tret" ); + +/* DWORD WINAPI GetCurrentThreadId(void) */ +__ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" ); + +#else /* __i386__ */ + /********************************************************************** * SetLastError [KERNEL.147] [KERNEL32.497] Sets the last-error code. - * - * RETURNS - * None. */ -#undef SetLastError void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */ { NtCurrentTeb()->last_error = error; } +/********************************************************************** + * GetLastError [KERNEL.148] [KERNEL32.227] Returns last-error code. + */ +DWORD WINAPI GetLastError(void) +{ + return NtCurrentTeb()->last_error; +} /*********************************************************************** * GetCurrentThreadId [KERNEL32.201] Returns thread identifier. - * - * RETURNS - * Thread identifier of calling thread */ -#undef GetCurrentThreadId DWORD WINAPI GetCurrentThreadId(void) { return (DWORD)NtCurrentTeb()->tid; } + +#endif /* __i386__ */ diff --git a/win32/Makefile.in b/win32/Makefile.in index ecfc1f28b4b..ca3feca2a9b 100644 --- a/win32/Makefile.in +++ b/win32/Makefile.in @@ -18,7 +18,6 @@ C_SRCS = \ ordinals.c \ process.c \ struct32.c \ - thread.c \ time.c all: $(MODULE).o diff --git a/win32/thread.c b/win32/thread.c deleted file mode 100644 index 1fd6d50200d..00000000000 --- a/win32/thread.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Win32 kernel functions - * - * Copyright 1995 Martin von Loewis - * Copyright 1997 Onno Hovers - */ - -#include -#include - -#include "winbase.h" -#include "windef.h" -#include "winerror.h" - - -/* - * FIXME: - * The c functions do not protect from non-interlocked accesses - * This is no problem as long as we do not have multiple Win32 threads - * or processes. - * The assembly macro's do protect from non-interlocked access, - * but they will only work for i386 systems with GCC. - */ - -/************************************************************************ -* InterlockedIncrement [KERNEL32] * -* * -* InterlockedIncrement adds 1 to a long variable and returns * -* - a negative number if the result < 0 * -* - zero if the result == 0 * -* - a positive number if the result > 0 * -* * -* The returned number need not be equal to the result!!!! * -************************************************************************/ - -LONG WINAPI InterlockedIncrement(LPLONG lpAddend) -{ -#if defined(__i386__)&&defined(__GNUC__) - long ret; - __asm__ - ( - "\tlock\n" /* for SMP systems */ - "\tincl (%1)\n" - "\tje 2f\n" - "\tjl 1f\n" - "\tincl %0\n" - "\tjmp 2f\n" - "1:\tdec %0\n" - "2:\n" - :"=r" (ret):"r" (lpAddend), "0" (0): "memory" - ); - return ret; -#else - LONG ret; - /* StopAllThreadsAndProcesses() */ - - (*lpAddend)++; - ret=*lpAddend; - - /* ResumeAllThreadsAndProcesses() */ - return ret; -#endif -} - -/************************************************************************ -* InterlockedDecrement [KERNEL32] * -* * -* InterlockedIncrement adds 1 to a long variable and returns * -* - a negative number if the result < 0 * -* - zero if the result == 0 * -* - a positive number if the result > 0 * -* * -* The returned number need not be equal to the result!!!! * -************************************************************************/ - -LONG WINAPI InterlockedDecrement(LPLONG lpAddend) -{ -#if defined(__i386__)&&defined(__GNUC__) - LONG ret; - __asm__ - ( - "\tlock\n" /* for SMP systems */ - "\tdecl (%1)\n" - "\tje 2f\n" - "\tjl 1f\n" - "\tincl %0\n" - "\tjmp 2f\n" - "1:\tdec %0\n" - "2:\n" - :"=r" (ret):"r" (lpAddend), "0" (0): "memory" - ); - return ret; -#else - LONG ret; - /* StopAllThreadsAndProcesses() */ - - (*lpAddend)--; - ret=*lpAddend; - - /* ResumeAllThreadsAndProcesses() */ - return ret; -#endif -} - -/************************************************************************ - * InterlockedExchange [KERNEL32.???] - * - * Atomically exchanges a pair of values. - * - * RETURNS - * Prior value of value pointed to by Target - */ -LONG WINAPI InterlockedExchange( - LPLONG target, /* Address of 32-bit value to exchange */ - LONG value /* New value for the value pointed to by target */ -) { -#if defined(__i386__)&&defined(__GNUC__) - LONG ret; - __asm__ ( /* lock for SMP systems */ - "lock\n\txchgl %0,(%1)" - :"=r" (ret):"r" (target), "0" (value):"memory" ); - return ret; -#else - LONG ret; - /* StopAllThreadsAndProcesses() */ - - ret=*target; - *target=value; - - /* ResumeAllThreadsAndProcesses() */ - return ret; -#endif -} - -/************************************************************************ - * InterlockedCompareExchange [KERNEL32.879] - * - * Atomically compares Destination and Comperand, and if found equal exchanges - * the value of Destination with Exchange - * - * RETURNS - * Prior value of value pointed to by Destination - */ -PVOID WINAPI InterlockedCompareExchange( - PVOID *Destination, /* Address of 32-bit value to exchange */ - PVOID Exchange, /* change value, 32 bits */ - PVOID Comperand /* value to compare, 32 bits */ -) { -#if defined(__i386__)&&defined(__GNUC__) - PVOID ret; - __asm__ ( /* lock for SMP systems */ - "lock\n\t" - "cmpxchgl %2,(%1)" - :"=a" (ret) - :"r" (Destination),"r" (Exchange), "0" (Comperand) - :"memory" ); - return ret; -#else - PVOID ret; - /* StopAllThreadsAndProcesses() */ - - ret=*Destination; - if(*Destination==Comperand) *Destination=Exchange; - - /* ResumeAllThreadsAndProcesses() */ - return ret; -#endif -} - -/************************************************************************ - * InterlockedExchangeAdd [KERNEL32.880] - * - * Atomically adds Increment to Addend and returns the previous value of - * Addend - * - * RETURNS - * Prior value of value pointed to by cwAddendTarget - */ -LONG WINAPI InterlockedExchangeAdd( - PLONG Addend, /* Address of 32-bit value to exchange */ - LONG Increment /* Value to add */ -) { -#if defined(__i386__)&&defined(__GNUC__) - LONG ret; - __asm__ ( /* lock for SMP systems */ - "lock\n\t" - "xaddl %0,(%1)" - :"=r" (ret) - :"r" (Addend), "0" (Increment) - :"memory" ); - return ret; -#else - LONG ret; - /* StopAllThreadsAndProcesses() */ - - ret = *Addend; - *Addend += Increment; - - /* ResumeAllThreadsAndProcesses() */ - return ret; -#endif -}