remove wine's broken _beginthread() and _endthread() and implement them properly
authorThomas Bluemel <thomas@reactsoft.com>
Fri, 13 Jan 2006 17:32:59 +0000 (17:32 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Fri, 13 Jan 2006 17:32:59 +0000 (17:32 +0000)
svn path=/trunk/; revision=20834

reactos/lib/crt/crt.xml
reactos/lib/crt/include/internal/tls.h
reactos/lib/crt/misc/tls.c
reactos/lib/crt/process/thread.c
reactos/lib/crt/wine/thread.c [deleted file]

index 2db3f46..1a2f64f 100644 (file)
                <file>cppexcept.c</file>
                <file>heap.c</file>
                <file>scanf.c</file>
-               <file>thread.c</file>
                <file>undname.c</file>
        </directory>
 </module>
index 4adcc83..79ad295 100644 (file)
 
 typedef struct _ThreadData
 {
+  HANDLE hThread;               /* handle to the current thread */
+  void (__cdecl *start_address)(void*); /* the start address supplied by _beginthread() */
+  void* arglist;                /* the argument list supplied by _beginthread() */
+
   int terrno;                   /* *nix error code */
   unsigned long tdoserrno;      /* Win32 error code (for I/O only) */
   unsigned __int64 tnext;       /* used by rand/srand */
@@ -41,7 +45,8 @@ typedef struct _ThreadData
 int CreateThreadData(void);
 void DestroyThreadData(void);
 
-void FreeThreadData(PTHREADDATA ptd);
+int SetThreadData(PTHREADDATA ThreadData);
+void FreeThreadData(PTHREADDATA ThreadData);
 PTHREADDATA GetThreadData(void);
 
 #endif /* __MSVCRT_INTERNAL_TLS_H */
index 9fa6d03..41414f3 100644 (file)
@@ -4,7 +4,7 @@
 #include <internal/rterror.h>
 
 
-static unsigned long TlsIndex = (unsigned long)-1;
+static DWORD TlsIndex = TLS_OUT_OF_INDEXES;
 
 
 static void InitThreadData(PTHREADDATA ThreadData)
@@ -19,19 +19,10 @@ static void InitThreadData(PTHREADDATA ThreadData)
 }
 
 
-int CreateThreadData(void)
+int SetThreadData(PTHREADDATA ThreadData)
 {
-   PTHREADDATA ThreadData;
-
-   TlsIndex = TlsAlloc();
-   if (TlsIndex == (unsigned long)-1)
-     return FALSE;
-
-   ThreadData = (PTHREADDATA)calloc(1, sizeof(THREADDATA));
-   if (ThreadData == NULL)
-     return FALSE;
-
-   if(!TlsSetValue(TlsIndex, (LPVOID)ThreadData))
+   if(TlsIndex == TLS_OUT_OF_INDEXES ||
+      !TlsSetValue(TlsIndex, ThreadData))
      return FALSE;
 
    InitThreadData(ThreadData);
@@ -40,19 +31,26 @@ int CreateThreadData(void)
 }
 
 
+int CreateThreadData(void)
+{
+   TlsIndex = TlsAlloc();
+   return (TlsIndex != TLS_OUT_OF_INDEXES);
+}
+
+
 void DestroyThreadData(void)
 {
-   if (TlsIndex != (unsigned long)-1)
+   if (TlsIndex != TLS_OUT_OF_INDEXES)
      {
        TlsFree(TlsIndex);
-       TlsIndex = (unsigned long)-1;
+       TlsIndex = TLS_OUT_OF_INDEXES;
      }
 }
 
 
 void FreeThreadData(PTHREADDATA ThreadData)
 {
-   if (TlsIndex != (unsigned long)-1)
+   if (TlsIndex != TLS_OUT_OF_INDEXES)
      {
        if (ThreadData == NULL)
           ThreadData = TlsGetValue(TlsIndex);
@@ -84,6 +82,8 @@ PTHREADDATA GetThreadData(void)
             TlsSetValue(TlsIndex, (LPVOID)ThreadData);
 
             InitThreadData(ThreadData);
+
+             ThreadData->hThread = GetCurrentThread();
          }
        else
          {
index d058d72..2b86729 100644 (file)
 #include <precomp.h>
 
-#if 0
+void _endthread(void);
+
+static DWORD WINAPI
+_beginthread_start(PVOID lpParameter)
+{
+    PTHREADDATA ThreadData = (PTHREADDATA)lpParameter;
+
+    if (SetThreadData(ThreadData))
+    {
+        /* FIXME - wrap start_address in SEH! */
+        ThreadData->start_address(ThreadData->arglist);
+
+        _endthread();
+    }
+    else
+    {
+        /* couldn't set the thread data, free it before terminating */
+        free(ThreadData);
+    }
+
+    ExitThread(0);
+}
+
+
 /*
- * @unimplemented
+ * @implemented
+ *
+ * FIXME: the return type should be uintptr_t
  */
 unsigned long _beginthread(
     void (__cdecl *start_address)(void*),
     unsigned stack_size,
     void* arglist)
 {
-    __set_errno ( ENOSYS );
-    return (unsigned long)-1;
+    HANDLE hThread;
+    PTHREADDATA ThreadData;
+
+    if (start_address == NULL) {
+        __set_errno(EINVAL);
+        return (unsigned long)-1;
+    }
+
+    /* allocate the thread data structure already here instead of allocating the
+       thread data structure in the thread itself. this way we can pass an error
+       code to the caller in case we don't have sufficient resources */
+    ThreadData = malloc(sizeof(THREADDATA));
+    if (ThreadData == NULL)
+    {
+        __set_errno(EAGAIN);
+        return (unsigned long)-1;
+    }
+
+    ThreadData->start_address = start_address;
+    ThreadData->arglist = arglist;
+
+    hThread = CreateThread(NULL,
+                           stack_size,
+                           _beginthread_start,
+                           ThreadData,
+                           CREATE_SUSPENDED,
+                           NULL);
+    if (hThread == NULL)
+    {
+        free(ThreadData);
+        __set_errno(EAGAIN);
+        return (unsigned long)-1;
+    }
+
+    ThreadData->hThread = hThread;
+
+    if (ResumeThread(hThread) == (DWORD)-1)
+    {
+        CloseHandle(hThread);
+
+        /* freeing the ThreadData _could_ cause a crash, but only in case someone
+           else resumed the thread and it got to free the context before we actually
+           get here, but that's _very_ unlikely! */
+        free(ThreadData);
+        __set_errno(EAGAIN);
+        return (unsigned long)-1;
+    }
+
+    return (unsigned long)hThread;
 }
-#endif
+
 /*
- * @unimplemented
+ * @implemented
  */
 void _endthread(void)
 {
-}
+    PTHREADDATA ThreadData = GetThreadData();
+
+    /* close the thread handle */
+    CloseHandle(ThreadData->hThread);
 
-/* EOF */
+    /* NOTE: the thread data will be freed in the thread detach routine that will
+             call FreeThreadData */
+
+    ExitThread(0);
+}
diff --git a/reactos/lib/crt/wine/thread.c b/reactos/lib/crt/wine/thread.c
deleted file mode 100644 (file)
index d1574d6..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * msvcrt.dll thread functions
- *
- * Copyright 2000 Jon Griffiths
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <precomp.h>
-#include <internal/wine/msvcrt.h>
-
-#include <malloc.h>
-#include <process.h>
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
-
-void _amsg_exit (int errnum);
-/* Index to TLS */
-DWORD MSVCRT_tls_index;
-
-typedef void (*_beginthread_start_routine_t)(void *);
-typedef unsigned int (__stdcall *_beginthreadex_start_routine_t)(void *);
-
-/********************************************************************/
-
-typedef struct {
-  _beginthread_start_routine_t start_address;
-  void *arglist;
-} _beginthread_trampoline_t;
-
-/*********************************************************************
- *             msvcrt_get_thread_data
- *
- * Return the thread local storage structure.
- */
-MSVCRT_thread_data *msvcrt_get_thread_data(void)
-{
-    MSVCRT_thread_data *ptr;
-    DWORD err = GetLastError();  /* need to preserve last error */
-
-    if (!(ptr = TlsGetValue( MSVCRT_tls_index )))
-    {
-        if (!(ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptr) )))
-                   _amsg_exit( _RT_THREAD );
-        if (!TlsSetValue( MSVCRT_tls_index, ptr ))
-                       _amsg_exit( _RT_THREAD );
-        if (!TlsSetValue( MSVCRT_tls_index, ptr ))
-                       _amsg_exit( _RT_THREAD );
-    }
-    SetLastError( err );
-    return ptr;
-}
-
-/*********************************************************************
- *             _beginthread_trampoline
- */
-static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
-{
-    _beginthread_trampoline_t local_trampoline;
-
-    /* Maybe it's just being paranoid, but freeing arg right
-     * away seems safer.
-     */
-    memcpy(&local_trampoline,arg,sizeof(local_trampoline));
-       free(arg);
-
-    local_trampoline.start_address(local_trampoline.arglist);
-    return 0;
-}
-
-/*********************************************************************
- *             _beginthread (MSVCRT.@)
- */
-unsigned long _beginthread(
-  _beginthread_start_routine_t start_address, /* [in] Start address of routine that begins execution of new thread */
-  unsigned int stack_size, /* [in] Stack size for new thread or 0 */
-  void *arglist)           /* [in] Argument list to be passed to new thread or NULL */
-{
-  _beginthread_trampoline_t* trampoline;
-
-  TRACE("(%p, %d, %p)\n", start_address, stack_size, arglist);
-
-  /* Allocate the trampoline here so that it is still valid when the thread
-   * starts... typically after this function has returned.
-   * _beginthread_trampoline is responsible for freeing the trampoline
-   */
-  trampoline=malloc(sizeof(*trampoline));
-  trampoline->start_address = start_address;
-  trampoline->arglist = arglist;
-
-  /* FIXME */
-  return (unsigned long)CreateThread(NULL, stack_size, _beginthread_trampoline,
-                                    trampoline, 0, NULL);
-}