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