remove wine's broken _beginthread() and _endthread() and implement them properly

svn path=/trunk/; revision=20834
This commit is contained in:
Thomas Bluemel 2006-01-13 17:32:59 +00:00
parent 4f5e52acac
commit 0501de01bb
5 changed files with 109 additions and 134 deletions

View file

@ -385,7 +385,6 @@
<file>cppexcept.c</file>
<file>heap.c</file>
<file>scanf.c</file>
<file>thread.c</file>
<file>undname.c</file>
</directory>
</module>

View file

@ -17,6 +17,10 @@
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 */

View 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
{

View file

@ -1,23 +1,102 @@
#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();
/* EOF */
/* close the thread handle */
CloseHandle(ThreadData->hThread);
/* NOTE: the thread data will be freed in the thread detach routine that will
call FreeThreadData */
ExitThread(0);
}

View file

@ -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);
}