From f06d99f67a5d5dd1b7d8e56ae1056bf1df32ef1f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 8 Dec 2008 19:25:25 +0100 Subject: [PATCH] include: Implemented inline asm functions for x86_64. Export Interlocked* only on i386. --- dlls/kernel32/kernel32.spec | 10 +-- dlls/kernel32/sync.c | 89 ------------------------ include/winbase.h | 162 +++++++++++++++++++++++++++++++++++--------- include/wine/port.h | 16 ++++- 4 files changed, 147 insertions(+), 130 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 8100b921a6d..a5a9bc6d4b9 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -722,12 +722,12 @@ @ stdcall InitializeCriticalSectionAndSpinCount(ptr long) @ stdcall InitializeCriticalSectionEx(ptr long long) @ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead -@ stdcall InterlockedCompareExchange (ptr long long) -@ stdcall InterlockedDecrement(ptr) -@ stdcall InterlockedExchange(ptr long) -@ stdcall InterlockedExchangeAdd (ptr long ) +@ stdcall -arch=i386 InterlockedCompareExchange (ptr long long) +@ stdcall -arch=i386 InterlockedDecrement(ptr) +@ stdcall -arch=i386 InterlockedExchange(ptr long) +@ stdcall -arch=i386 InterlockedExchangeAdd (ptr long ) @ stdcall InterlockedFlushSList(ptr) ntdll.RtlInterlockedFlushSList -@ stdcall InterlockedIncrement(ptr) +@ stdcall -arch=i386 InterlockedIncrement(ptr) @ stdcall InterlockedPopEntrySList(ptr) ntdll.RtlInterlockedPopEntrySList @ stdcall InterlockedPushEntrySList(ptr ptr) ntdll.RtlInterlockedPushEntrySList @ stub InvalidateConsoleDIBits diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 2318c918273..d65bd1249ec 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -2314,93 +2314,4 @@ __ASM_GLOBAL_FUNC(InterlockedDecrement, "decl %eax\n\t" "ret $4") -#else /* __i386__ */ - -/*********************************************************************** - * InterlockedCompareExchange (KERNEL32.@) - * - * Atomically swap one value with another. - * - * PARAMS - * dest [I/O] The value to replace - * xchq [I] The value to be swapped - * compare [I] The value to compare to dest - * - * RETURNS - * The resulting value of dest. - * - * NOTES - * dest is updated only if it is equal to compare, otherwise no swap is done. - */ -LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ) -{ - return interlocked_cmpxchg( (int *)dest, xchg, compare ); -} - -/*********************************************************************** - * InterlockedExchange (KERNEL32.@) - * - * Atomically swap one value with another. - * - * PARAMS - * dest [I/O] The value to replace - * val [I] The value to be swapped - * - * RETURNS - * The resulting value of dest. - */ -LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val ) -{ - return interlocked_xchg( (int *)dest, val ); -} - -/*********************************************************************** - * InterlockedExchangeAdd (KERNEL32.@) - * - * Atomically add one value to another. - * - * PARAMS - * dest [I/O] The value to add to - * incr [I] The value to be added - * - * RETURNS - * The resulting value of dest. - */ -LONG WINAPI InterlockedExchangeAdd( LONG volatile *dest, LONG incr ) -{ - return interlocked_xchg_add( (int *)dest, incr ); -} - -/*********************************************************************** - * InterlockedIncrement (KERNEL32.@) - * - * Atomically increment a value. - * - * PARAMS - * dest [I/O] The value to increment - * - * RETURNS - * The resulting value of dest. - */ -LONG WINAPI InterlockedIncrement( LONG volatile *dest ) -{ - return interlocked_xchg_add( (int *)dest, 1 ) + 1; -} - -/*********************************************************************** - * InterlockedDecrement (KERNEL32.@) - * - * Atomically decrement a value. - * - * PARAMS - * dest [I/O] The value to decrement - * - * RETURNS - * The resulting value of dest. - */ -LONG WINAPI InterlockedDecrement( LONG volatile *dest ) -{ - return interlocked_xchg_add( (int *)dest, -1 ) - 1; -} - #endif /* __i386__ */ diff --git a/include/winbase.h b/include/winbase.h index 6b19a4b2d0e..6fa4dce16dd 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2315,9 +2315,10 @@ extern char *wine_get_unix_file_name( LPCWSTR dos ); extern WCHAR *wine_get_dos_file_name( LPCSTR str ); -/* a few optimizations for i386/gcc */ +/* Interlocked functions */ -#if defined(__i386__) && defined(__GNUC__) && defined(__WINESRC__) && !defined(_NTSYSTEM_) +#ifdef __i386__ +# if defined(__GNUC__) && !defined(_NTSYSTEM_) extern inline LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ); extern inline LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ) @@ -2358,11 +2359,118 @@ extern inline LONG WINAPI InterlockedDecrement( LONG volatile *dest ) return InterlockedExchangeAdd( dest, -1 ) - 1; } +# else /* __GNUC__ */ + +WINBASEAPI LONG WINAPI InterlockedCompareExchange(LONG volatile*,LONG,LONG); +WINBASEAPI LONG WINAPI InterlockedDecrement(LONG volatile*); +WINBASEAPI LONG WINAPI InterlockedExchange(LONG volatile*,LONG); +WINBASEAPI LONG WINAPI InterlockedExchangeAdd(LONG volatile*,LONG); +WINBASEAPI LONG WINAPI InterlockedIncrement(LONG volatile*); + +# endif /* __GNUC__ */ + +static inline PVOID WINAPI InterlockedCompareExchangePointer( PVOID volatile *dest, PVOID xchg, PVOID compare ) +{ + return (PVOID)InterlockedCompareExchange( (LONG volatile*)dest, (LONG)xchg, (LONG)compare ); +} + +static inline PVOID WINAPI InterlockedExchangePointer( PVOID volatile *dest, PVOID val ) +{ + return (PVOID)InterlockedExchange( (LONG volatile*)dest, (LONG)val ); +} + +#else /* __i386__ */ + +static inline LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ) +{ +#if defined(__x86_64__) && defined(__GNUC__) + LONG ret; + __asm__ __volatile__( "lock; cmpxchgl %2,(%1)" + : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); + return ret; +#else + extern int interlocked_cmpxchg( int *dest, int xchg, int compare ); + return interlocked_cmpxchg( (int *)dest, xchg, compare ); +#endif +} + +static inline PVOID WINAPI InterlockedCompareExchangePointer( PVOID volatile *dest, PVOID xchg, PVOID compare ) +{ +#if defined(__x86_64__) && defined(__GNUC__) + PVOID ret; + __asm__ __volatile__( "lock; cmpxchgq %2,(%1)" + : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); + return ret; +#else + extern void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare ); + return interlocked_cmpxchg_ptr( (void **)dest, xchg, compare ); +#endif +} + +static inline LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val ) +{ +#if defined(__x86_64__) && defined(__GNUC__) + LONG ret; + __asm__ __volatile__( "lock; xchgl %0,(%1)" + : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); + return ret; +#else + extern int interlocked_xchg( int *dest, int val ); + return interlocked_xchg( (int *)dest, val ); +#endif +} + +static inline PVOID WINAPI InterlockedExchangePointer( PVOID volatile *dest, PVOID val ) +{ +#if defined(__x86_64__) && defined(__GNUC__) + PVOID ret; + __asm__ __volatile__( "lock; xchgq %0,(%1)" + : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); + return ret; +#else + extern void *interlocked_xchg_ptr( void **dest, void *val ); + return interlocked_xchg_ptr( (void **)dest, val ); +#endif +} + +static inline LONG WINAPI InterlockedExchangeAdd( LONG volatile *dest, LONG incr ) +{ +#if defined(__x86_64__) && defined(__GNUC__) + LONG ret; + __asm__ __volatile__( "lock; xaddl %0,(%1)" + : "=r" (ret) : "r" (dest), "0" (incr) : "memory" ); + return ret; +#else + extern int interlocked_xchg_add( int *dest, int incr ); + return interlocked_xchg_add( (int *)dest, incr ); +#endif +} + +static inline LONG WINAPI InterlockedIncrement( LONG volatile *dest ) +{ + return InterlockedExchangeAdd( dest, 1 ) + 1; +} + +static inline LONG WINAPI InterlockedDecrement( LONG volatile *dest ) +{ + return InterlockedExchangeAdd( dest, -1 ) - 1; +} + +#endif /* __i386__ */ + +/* A few optimizations for gcc */ + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64)) + extern inline DWORD WINAPI GetLastError(void); extern inline DWORD WINAPI GetLastError(void) { DWORD ret; +#ifdef __x86_64__ + __asm__ __volatile__( ".byte 0x65\n\tmovl 0x68,%0" : "=r" (ret) ); +#else __asm__ __volatile__( ".byte 0x64\n\tmovl 0x34,%0" : "=r" (ret) ); +#endif return ret; } @@ -2370,7 +2478,11 @@ extern inline DWORD WINAPI GetCurrentProcessId(void); extern inline DWORD WINAPI GetCurrentProcessId(void) { DWORD ret; +#ifdef __x86_64__ + __asm__ __volatile__( ".byte 0x65\n\tmovl 0x40,%0" : "=r" (ret) ); +#else __asm__ __volatile__( ".byte 0x64\n\tmovl 0x20,%0" : "=r" (ret) ); +#endif return ret; } @@ -2378,62 +2490,46 @@ extern inline DWORD WINAPI GetCurrentThreadId(void); extern inline DWORD WINAPI GetCurrentThreadId(void) { DWORD ret; +#ifdef __x86_64__ + __asm__ __volatile__( ".byte 0x65\n\tmovl 0x48,%0" : "=r" (ret) ); +#else __asm__ __volatile__( ".byte 0x64\n\tmovl 0x24,%0" : "=r" (ret) ); +#endif return ret; } extern inline void WINAPI SetLastError( DWORD err ); extern inline void WINAPI SetLastError( DWORD err ) { +#ifdef __x86_64__ + __asm__ __volatile__( ".byte 0x65\n\tmovl %0,0x68" : : "r" (err) : "memory" ); +#else __asm__ __volatile__( ".byte 0x64\n\tmovl %0,0x34" : : "r" (err) : "memory" ); +#endif } extern inline HANDLE WINAPI GetProcessHeap(void); extern inline HANDLE WINAPI GetProcessHeap(void) { HANDLE *pdb; +#ifdef __x86_64__ + __asm__ __volatile__( ".byte 0x64\n\tmovq 0x60,%0" : "=r" (pdb) ); + return pdb[0x30 / sizeof(HANDLE)]; /* get dword at offset 0x30 in pdb */ +#else __asm__ __volatile__( ".byte 0x64\n\tmovl 0x30,%0" : "=r" (pdb) ); return pdb[0x18 / sizeof(HANDLE)]; /* get dword at offset 0x18 in pdb */ +#endif } -#else /* __i386__ && __GNUC__ && __WINESRC__ && !_NTSYSTEM_ */ +#else /* __GNUC__ */ WINBASEAPI DWORD WINAPI GetCurrentProcessId(void); WINBASEAPI DWORD WINAPI GetCurrentThreadId(void); WINBASEAPI DWORD WINAPI GetLastError(void); WINBASEAPI HANDLE WINAPI GetProcessHeap(void); -WINBASEAPI LONG WINAPI InterlockedCompareExchange(LONG volatile*,LONG,LONG); -WINBASEAPI LONG WINAPI InterlockedDecrement(LONG volatile*); -WINBASEAPI LONG WINAPI InterlockedExchange(LONG volatile*,LONG); -WINBASEAPI LONG WINAPI InterlockedExchangeAdd(LONG volatile*,LONG); -WINBASEAPI LONG WINAPI InterlockedIncrement(LONG volatile*); WINBASEAPI VOID WINAPI SetLastError(DWORD); -#endif /* __i386__ && __GNUC__ && __WINESRC__ && !_NTSYSTEM_ */ - -static inline PVOID WINAPI InterlockedCompareExchangePointer( PVOID volatile *dest, PVOID xchg, PVOID compare ) -{ -#if defined(__x86_64__) && defined(__GNUC__) - PVOID ret; - __asm__ __volatile__( "lock; cmpxchgq %2,(%1)" - : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); - return ret; -#else - return (PVOID)InterlockedCompareExchange( (LONG volatile*)dest, (LONG)xchg, (LONG)compare ); -#endif -} - -static inline PVOID WINAPI InterlockedExchangePointer( PVOID volatile *dest, PVOID val ) -{ -#if defined(__x86_64__) && defined(__GNUC__) - PVOID ret; - __asm__ __volatile__( "lock; xchgq %0,(%1)" - : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); - return ret; -#else - return (PVOID)InterlockedExchange( (LONG volatile*)dest, (LONG)val ); -#endif -} +#endif /* __GNUC__ */ #ifdef __WINESRC__ #define GetCurrentProcess() ((HANDLE)~(ULONG_PTR)0) diff --git a/include/wine/port.h b/include/wine/port.h index 4f9f8ab539d..68ded3d5ac2 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -380,7 +380,7 @@ extern int spawnvp(int mode, const char *cmdname, const char * const argv[]); /* Interlocked functions */ -#if defined(__i386__) && defined(__GNUC__) +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) extern inline int interlocked_cmpxchg( int *dest, int xchg, int compare ); extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare ); @@ -400,8 +400,13 @@ extern inline int interlocked_cmpxchg( int *dest, int xchg, int compare ) extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare ) { void *ret; +#ifdef __x86_64__ + __asm__ __volatile__( "lock; cmpxchgq %2,(%1)" + : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); +#else __asm__ __volatile__( "lock; cmpxchgl %2,(%1)" : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" ); +#endif return ret; } @@ -416,8 +421,13 @@ extern inline int interlocked_xchg( int *dest, int val ) extern inline void *interlocked_xchg_ptr( void **dest, void *val ) { void *ret; +#ifdef __x86_64__ + __asm__ __volatile__( "lock; xchgq %0,(%1)" + : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); +#else __asm__ __volatile__( "lock; xchgl %0,(%1)" : "=r" (ret) : "r" (dest), "0" (val) : "memory" ); +#endif return ret; } @@ -429,7 +439,7 @@ extern inline int interlocked_xchg_add( int *dest, int incr ) return ret; } -#else /* __i386___ && __GNUC__ */ +#else /* __GNUC__ */ extern int interlocked_cmpxchg( int *dest, int xchg, int compare ); extern void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare ); @@ -438,7 +448,7 @@ extern int interlocked_xchg( int *dest, int val ); extern void *interlocked_xchg_ptr( void **dest, void *val ); extern int interlocked_xchg_add( int *dest, int incr ); -#endif /* __i386___ && __GNUC__ */ +#endif /* __GNUC__ */ #else /* NO_LIBWINE_PORT */ -- 2.11.4.GIT