[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