Henri Verbeet : ntdll: The FPU control word for newly created threads is 0x27f.
Alexandre Julliard
julliard at winehq.org
Thu Jun 17 11:17:15 CDT 2010
Module: wine
Branch: master
Commit: 772a5c7c09a2568cd0ad2358f307c3eaa5fe4912
URL: http://source.winehq.org/git/wine.git/?a=commit;h=772a5c7c09a2568cd0ad2358f307c3eaa5fe4912
Author: Henri Verbeet <hverbeet at codeweavers.com>
Date: Thu Jun 17 10:17:15 2010 +0200
ntdll: The FPU control word for newly created threads is 0x27f.
This fixes a regression introduced by
e6611e22fb037a879205f1330d1a3485f9f18705.
---
dlls/kernel32/tests/thread.c | 84 ++++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/signal_i386.c | 10 +++++
dlls/ntdll/signal_x86_64.c | 10 +++++
3 files changed, 104 insertions(+), 0 deletions(-)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index 4c4e764..df87ae0 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -1329,6 +1329,87 @@ static void test_ThreadErrorMode(void)
pSetThreadErrorMode(oldmode, NULL);
}
+static inline void set_fpu_cw(WORD cw)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
+#endif
+}
+
+static inline WORD get_fpu_cw(void)
+{
+ WORD cw = 0;
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ volatile ("fnstcw %0" : "=m" (cw));
+#endif
+ return cw;
+}
+
+struct fpu_thread_ctx
+{
+ WORD cw;
+ HANDLE finished;
+};
+
+static DWORD WINAPI fpu_thread(void *param)
+{
+ struct fpu_thread_ctx *ctx = param;
+ BOOL ret;
+
+ ctx->cw = get_fpu_cw();
+
+ ret = SetEvent(ctx->finished);
+ ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
+
+ return 0;
+}
+
+static WORD get_thread_fpu_cw(void)
+{
+ struct fpu_thread_ctx ctx;
+ DWORD tid, res;
+ HANDLE thread;
+
+ ctx.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
+
+ thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
+ ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
+
+ res = WaitForSingleObject(ctx.finished, INFINITE);
+ ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
+
+ res = CloseHandle(ctx.finished);
+ ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
+
+ return ctx.cw;
+}
+
+static void test_thread_fpu_cw(void)
+{
+ WORD initial_cw, cw;
+
+ initial_cw = get_fpu_cw();
+ ok(initial_cw == 0x37f, "Expected FPU control word 0x37f, got %#x.\n", initial_cw);
+
+ cw = get_thread_fpu_cw();
+ ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
+
+ set_fpu_cw(0xf60);
+ cw = get_fpu_cw();
+ ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
+
+ cw = get_thread_fpu_cw();
+ ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
+
+ cw = get_fpu_cw();
+ ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
+
+ set_fpu_cw(initial_cw);
+ cw = get_fpu_cw();
+ ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
+}
+
START_TEST(thread)
{
HINSTANCE lib;
@@ -1401,4 +1482,7 @@ START_TEST(thread)
test_RegisterWaitForSingleObject();
test_TLS();
test_ThreadErrorMode();
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ test_thread_fpu_cw();
+#endif
}
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 7a60c2a..b003436 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -2177,6 +2177,16 @@ void signal_init_thread( TEB *teb )
wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
wine_ldt_init_fs( thread_data->fs, &fs_entry );
thread_data->gs = wine_get_gs();
+
+ if (teb->Peb->ProcessHeap) /* Not for the inital thread. */
+ {
+ const WORD fpu_cw = 0x27f;
+#ifdef __GNUC__
+ __asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
+#else
+ FIXME("FPU setup not implemented for this platform.\n");
+#endif
+ }
}
/**********************************************************************
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index f509006..188224d 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -2344,6 +2344,16 @@ void signal_init_thread( TEB *teb )
ss.ss_size = signal_stack_size;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) perror( "sigaltstack" );
+
+ if (teb->Peb->ProcessHeap) /* Not for the inital thread. */
+ {
+ const WORD fpu_cw = 0x27f;
+#ifdef __GNUC__
+ __asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
+#else
+ FIXME("FPU setup not implemented for this platform.\n");
+#endif
+ }
}
/**********************************************************************
More information about the wine-cvs
mailing list