[PATCH] ntdll: The FPU control word for newly created threads is 0x27f.

Henri Verbeet hverbeet at codeweavers.com
Wed Jun 16 08:43:10 CDT 2010


---
 dlls/kernel32/tests/thread.c |   84 ++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/ntdll_misc.h      |    1 +
 dlls/ntdll/signal_i386.c     |   15 +++++++
 dlls/ntdll/signal_powerpc.c  |    9 ++++
 dlls/ntdll/signal_sparc.c    |    9 ++++
 dlls/ntdll/signal_x86_64.c   |   15 +++++++
 dlls/ntdll/thread.c          |    1 +
 7 files changed, 134 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/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index c7b721a..617b103 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -62,6 +62,7 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
 extern NTSTATUS signal_alloc_thread( TEB **teb );
 extern void signal_free_thread( TEB *teb );
 extern void signal_init_thread( TEB *teb );
+extern void signal_init_thread_fpu( void );
 extern void signal_init_process(void);
 extern void version_init( const WCHAR *appname );
 extern void debug_init(void);
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 7a60c2a..ced0258 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -2179,6 +2179,21 @@ void signal_init_thread( TEB *teb )
     thread_data->gs = wine_get_gs();
 }
 
+
+/**********************************************************************
+ *              signal_init_thread_fpu
+ */
+void signal_init_thread_fpu( void )
+{
+    const WORD fpu_cw = 0x27f;
+#ifdef __GNUC__
+    __asm__ volatile ("fnclex; fldcw %0" : : "m" (fpu_cw));
+#else
+    FIXME("FPU setup not implemented for this platform.\n");
+#endif
+}
+
+
 /**********************************************************************
  *		signal_init_process
  */
diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
index 662d97b..5c4c417 100644
--- a/dlls/ntdll/signal_powerpc.c
+++ b/dlls/ntdll/signal_powerpc.c
@@ -1040,6 +1040,15 @@ void signal_init_thread( TEB *teb )
 
 
 /**********************************************************************
+ *              signal_init_thread_fpu
+ */
+void signal_init_thread_fpu( void )
+{
+    FIXME("FPU setup not implemented for this platform.\n");
+}
+
+
+/**********************************************************************
  *		signal_init_process
  */
 void signal_init_process(void)
diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c
index 660bc9c..7417541 100644
--- a/dlls/ntdll/signal_sparc.c
+++ b/dlls/ntdll/signal_sparc.c
@@ -775,6 +775,15 @@ void signal_init_thread( TEB *teb )
 
 
 /**********************************************************************
+ *              signal_init_thread_fpu
+ */
+void signal_init_thread_fpu( void )
+{
+    FIXME("FPU setup not implemented for this platform.\n");
+}
+
+
+/**********************************************************************
  *		signal_init_process
  */
 void signal_init_process(void)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index f509006..7dc0934 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -2346,6 +2346,21 @@ void signal_init_thread( TEB *teb )
     if (sigaltstack(&ss, NULL) == -1) perror( "sigaltstack" );
 }
 
+
+/**********************************************************************
+ *              signal_init_thread_fpu
+ */
+void signal_init_thread_fpu( void )
+{
+    const WORD fpu_cw = 0x27f;
+#ifdef __GNUC__
+    __asm__ volatile ("fnclex; fldcw %0" : : "m" (fpu_cw));
+#else
+    FIXME("FPU setup not implemented for this platform.\n");
+#endif
+}
+
+
 /**********************************************************************
  *		signal_init_process
  */
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 36f1499..0d383bd 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -384,6 +384,7 @@ static void start_thread( struct startup_info *info )
     thread_data->pthread_id = pthread_self();
 
     signal_init_thread( teb );
+    signal_init_thread_fpu();
     server_init_thread( func );
     pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
 
-- 
1.6.4.4




More information about the wine-patches mailing list