kernel/tests: Test behaviour of TPIDRURW register with threads on ARMv7 (try 2)

André Hentschel nerv at dawncrow.de
Thu Jul 4 15:58:40 CDT 2013


Thanks Dmitry, checking for GNUC for now.
Also adding a skip to not err out until linux kernel 3.11 is out.
---
 dlls/kernel32/tests/thread.c | 109 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 108 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index 9be0484..258dbee 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -25,11 +25,15 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-#include "wine/test.h"
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include <windef.h>
 #include <winbase.h>
 #include <winnt.h>
 #include <winerror.h>
+#include <winternl.h>
+
+#include "wine/test.h"
 
 /* Specify the number of simultaneous threads to test */
 #define NUM_THREADS 4
@@ -1432,6 +1436,106 @@ static void test_thread_fpu_cw(void)
 }
 #endif
 
+#if defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
+static inline void set_tpidrurw(DWORD tpidrurw)
+{
+    __asm__ volatile ("mcr	p15, 0, %0, c13, c0, 2" : : "r" (tpidrurw));
+}
+
+static inline DWORD get_tpidrurw(void)
+{
+    DWORD tpidrurw = 0;
+    __asm__ volatile ("mrc	p15, 0, %0, c13, c0, 2" : "=r" (tpidrurw));
+    return tpidrurw;
+}
+
+static BOOL test_thread_tpidrurw_teb(void)
+{
+    DWORD tpidrurw;
+    NTSTATUS status;
+    THREAD_BASIC_INFORMATION tbi;
+
+    tpidrurw = get_tpidrurw();
+
+    status = NtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
+    ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    return tpidrurw == (DWORD)tbi.TebBaseAddress;
+}
+
+struct tpidrurw_thread_ctx
+{
+    DWORD tpidrurw;
+    DWORD ret;
+    DWORD ms;
+    HANDLE finished;
+};
+
+static DWORD WINAPI tpidrurw_thread(void *param)
+{
+    struct tpidrurw_thread_ctx *ctx = param;
+    BOOL ret;
+
+    ok(test_thread_tpidrurw_teb(), "Expected tpidrurw to be the TebBaseAddress\n");
+
+    set_tpidrurw(ctx->tpidrurw);
+    Sleep(ctx->ms);
+    ctx->ret = get_tpidrurw();
+
+    ret = SetEvent(ctx->finished);
+    ok(ret, "SetEvent failed, last error %08x.\n", GetLastError());
+
+    return 0;
+}
+
+static void test_thread_tpidrurw(void)
+{
+    DWORD tpidrurw, res;
+    HANDLE thread;
+    struct tpidrurw_thread_ctx ctx1, ctx2;
+
+    if (!test_thread_tpidrurw_teb())
+    {
+        skip("TEB is not stored in tpidrurw, skipping rest of test\n");
+        return;
+    }
+
+    set_tpidrurw(0x18051987);
+
+    ctx1.tpidrurw = 0xdeadbeef;
+    ctx1.ms = 1000;
+    ctx1.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ok(!!ctx1.finished, "Failed to create event, last error %08x.\n", GetLastError());
+
+    thread = CreateThread(NULL, 0, tpidrurw_thread, &ctx1, 0, NULL);
+    ok(!!thread, "Failed to create thread, last error %08x.\n", GetLastError());
+
+    ctx2.tpidrurw = 0x12345678;
+    ctx2.ms = 500;
+    ctx2.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ok(!!ctx2.finished, "Failed to create event, last error %08x.\n", GetLastError());
+
+    thread = CreateThread(NULL, 0, tpidrurw_thread, &ctx2, 0, NULL);
+    ok(!!thread, "Failed to create thread, last error %08x.\n", GetLastError());
+
+    res = WaitForSingleObject(ctx2.finished, INFINITE);
+    ok(res == WAIT_OBJECT_0, "Wait failed (%08x), last error %08x.\n", res, GetLastError());
+
+    res = CloseHandle(ctx2.finished);
+    ok(!!res, "Failed to close event handle, last error %08x.\n", GetLastError());
+    ok(ctx2.ret == 0x12345678, "Expected tpidrurw 0x12345678, got %08x.\n", ctx2.ret);
+
+    res = WaitForSingleObject(ctx1.finished, INFINITE);
+    ok(res == WAIT_OBJECT_0, "Wait failed (%08x), last error %08x.\n", res, GetLastError());
+
+    res = CloseHandle(ctx1.finished);
+    ok(!!res, "Failed to close event handle, last error %08x.\n", GetLastError());
+    ok(ctx1.ret == 0xdeadbeef, "Expected tpidrurw 0xdeadbeef, got %08x.\n", ctx1.ret);
+
+    tpidrurw = get_tpidrurw();
+    ok(tpidrurw == 0x18051987, "Expected tpidrurw 0x18051987, got %08x.\n", tpidrurw);
+}
+#endif
+
 START_TEST(thread)
 {
    HINSTANCE lib;
@@ -1507,4 +1611,7 @@ START_TEST(thread)
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
    test_thread_fpu_cw();
 #endif
+#if defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
+   test_thread_tpidrurw();
+#endif
 }
-- 
1.8.1.2



More information about the wine-patches mailing list