[PATCH 14/15] kernel32: Add support for InterlockedCompareExchange64
Maarten Lankhorst
m.b.lankhorst at gmail.com
Thu Feb 4 06:50:41 CST 2010
---
dlls/kernel32/kernel32.spec | 1 +
dlls/kernel32/sync.c | 20 ++++++++++++++++++++
dlls/kernel32/tests/sync.c | 21 +++++++++++++++++++++
include/winbase.h | 23 +++++++++++++++++++++++
4 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index db9713f..c5a16e1 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -725,6 +725,7 @@
@ stdcall InitializeCriticalSectionEx(ptr long long)
@ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead
@ stdcall -arch=i386 InterlockedCompareExchange (ptr long long)
+@ stdcall -ret64 -arch=i386 InterlockedCompareExchange64 (ptr double double)
@ stdcall -arch=i386 InterlockedDecrement(ptr)
@ stdcall -arch=i386 InterlockedExchange(ptr long)
@ stdcall -arch=i386 InterlockedExchangeAdd (ptr long )
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index fbe055d..1667ead 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -2198,6 +2198,26 @@ __ASM_STDCALL_FUNC(InterlockedCompareExchange, 12,
"ret $12")
/***********************************************************************
+ * InterlockedCompareExchange64 (KERNEL32.@)
+ */
+/* LONG WINAPI InterlockedCompareExchange64( PLONG64 dest, LONG64 xchg, LONG64 compare ); */
+__ASM_STDCALL_FUNC(InterlockedCompareExchange64, 20,
+ "push %ebp\n\t"
+ "movl %esp,%ebp\n\t"
+ "push %esi\n\t"
+ "push %ebx\n\t"
+ "movl 8(%ebp),%esi\n\t"
+ "movl 12(%ebp),%ebx\n\t"
+ "movl 16(%ebp),%ecx\n\t"
+ "movl 20(%ebp),%eax\n\t"
+ "movl 24(%ebp),%edx\n\t"
+ "lock; cmpxchg8b (%esi)\n\t"
+ "pop %ebx\n\t"
+ "pop %esi\n\t"
+ "leave\n\t"
+ "ret $20")
+
+/***********************************************************************
* InterlockedExchange (KERNEL32.@)
*/
/* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index ea36fc6..53d4f02 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -35,6 +35,7 @@ static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
+static LONG64 (WINAPI *pInterlockedCompareExchange64)(volatile LONG64 *ret, LONG64 xchg, LONG64 compare);
static void test_signalandwait(void)
{
@@ -939,6 +940,23 @@ static void test_timer_queue(void)
GetLastError());
}
+static void test_interlocked64(void)
+{
+ LONG64 test, ret;
+ LONG64 magic = 0x12345678 + (((LONG64)0x9abcdef)<<(LONG64)32);
+ LONG64 magic2 = (((LONG64)0x12345678)<<(LONG64)32) + 0x9abcdef0;
+
+ test = magic;
+ ret = pInterlockedCompareExchange64(&test, magic2, magic2);
+ ok(ret == magic, "Ret 0x%x%08x unexpected\n", (UINT)(ret>>(LONG64)32), (UINT)ret);
+ ok(test == magic, "Test value changed to 0x%x%08x\n", (UINT)(test>>(LONG64)32), (UINT)test);
+
+ test = magic;
+ ret = pInterlockedCompareExchange64(&test, magic2, magic);
+ ok(ret == magic, "Ret 0x%x%08x unexpected\n", (UINT)(ret>>(LONG64)32), (UINT)ret);
+ ok(test == magic2, "Test value changed to 0x%x%08x\n", (UINT)(test>>(LONG64)32), (UINT)test);
+}
+
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
@@ -949,6 +967,7 @@ START_TEST(sync)
pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
+ pInterlockedCompareExchange64 = (void*)GetProcAddress(hdll, "InterlockedCompareExchange64");
test_signalandwait();
test_mutex();
@@ -958,4 +977,6 @@ START_TEST(sync)
test_waitable_timer();
test_iocp_callback();
test_timer_queue();
+ if (pInterlockedCompareExchange64)
+ test_interlocked64();
}
diff --git a/include/winbase.h b/include/winbase.h
index 1cd26f5..813eb6d 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2324,6 +2324,15 @@ extern inline LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG
return ret;
}
+extern inline LONG WINAPI InterlockedCompareExchange64( LONG64 volatile *dest, LONG64 xchg, LONG64 compare );
+extern inline LONG WINAPI InterlockedCompareExchange64( LONG64 volatile *dest, LONG64 xchg, LONG64 compare )
+{
+ LONG64 ret;
+ __asm__ __volatile__( "lock; cmpxchg8b (%1)"
+ : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+ return ret;
+}
+
extern inline LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val );
extern inline LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val )
{
@@ -2357,6 +2366,7 @@ extern inline LONG WINAPI InterlockedDecrement( LONG volatile *dest )
# else /* __GNUC__ */
WINBASEAPI LONG WINAPI InterlockedCompareExchange(LONG volatile*,LONG,LONG);
+WINBASEAPI LONG WINAPI InterlockedCompareExchange64(LONG64 volatile*,LONG64,LONG64);
WINBASEAPI LONG WINAPI InterlockedDecrement(LONG volatile*);
WINBASEAPI LONG WINAPI InterlockedExchange(LONG volatile*,LONG);
WINBASEAPI LONG WINAPI InterlockedExchangeAdd(LONG volatile*,LONG);
@@ -2402,6 +2412,19 @@ static inline PVOID WINAPI InterlockedCompareExchangePointer( PVOID volatile *de
#endif
}
+static inline LONG64 WINAPI InterlockedCompareExchange64( LONG64 volatile *dest, LONG64 xchg, LONG64 compare )
+{
+#if defined(__x86_64__) && defined(__GNUC__)
+ LONG64 ret;
+ __asm__ __volatile__( "lock; cmpxchgq %2,(%1)"
+ : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+ return ret;
+#else
+ extern void *interlocked_cmpxchg64( LONG64 **dest, LONG64 *xchg, LONG64 *compare );
+ return interlocked_cmpxchg64( (LONG64 **)dest, xchg, compare );
+#endif
+}
+
static inline LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val )
{
#if defined(__x86_64__) && defined(__GNUC__)
--
1.6.5
--------------010307080302010603020405--
More information about the wine-patches
mailing list