revert my last change
[reactos.git] / reactos / lib / crt / wine / thread.c
1 /*
2 * msvcrt.dll thread functions
3 *
4 * Copyright 2000 Jon Griffiths
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <precomp.h>
22 #include <internal/wine/msvcrt.h>
23
24 #include <malloc.h>
25 #include <process.h>
26
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
30
31 void _amsg_exit (int errnum);
32 /* Index to TLS */
33 DWORD MSVCRT_tls_index;
34
35 typedef void (*_beginthread_start_routine_t)(void *);
36 typedef unsigned int (__stdcall *_beginthreadex_start_routine_t)(void *);
37
38 /********************************************************************/
39
40 typedef struct {
41 _beginthread_start_routine_t start_address;
42 void *arglist;
43 } _beginthread_trampoline_t;
44
45 /*********************************************************************
46 * msvcrt_get_thread_data
47 *
48 * Return the thread local storage structure.
49 */
50 MSVCRT_thread_data *msvcrt_get_thread_data(void)
51 {
52 MSVCRT_thread_data *ptr;
53 DWORD err = GetLastError(); /* need to preserve last error */
54
55 if (!(ptr = TlsGetValue( MSVCRT_tls_index )))
56 {
57 if (!(ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptr) )))
58 _amsg_exit( _RT_THREAD );
59 if (!TlsSetValue( MSVCRT_tls_index, ptr ))
60 _amsg_exit( _RT_THREAD );
61 if (!TlsSetValue( MSVCRT_tls_index, ptr ))
62 _amsg_exit( _RT_THREAD );
63 }
64 SetLastError( err );
65 return ptr;
66 }
67
68 /*********************************************************************
69 * _beginthread_trampoline
70 */
71 static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
72 {
73 _beginthread_trampoline_t local_trampoline;
74
75 /* Maybe it's just being paranoid, but freeing arg right
76 * away seems safer.
77 */
78 memcpy(&local_trampoline,arg,sizeof(local_trampoline));
79 free(arg);
80
81 local_trampoline.start_address(local_trampoline.arglist);
82 return 0;
83 }
84
85 /*********************************************************************
86 * _beginthread (MSVCRT.@)
87 */
88 unsigned long _beginthread(
89 _beginthread_start_routine_t start_address, /* [in] Start address of routine that begins execution of new thread */
90 unsigned int stack_size, /* [in] Stack size for new thread or 0 */
91 void *arglist) /* [in] Argument list to be passed to new thread or NULL */
92 {
93 _beginthread_trampoline_t* trampoline;
94
95 TRACE("(%p, %d, %p)\n", start_address, stack_size, arglist);
96
97 /* Allocate the trampoline here so that it is still valid when the thread
98 * starts... typically after this function has returned.
99 * _beginthread_trampoline is responsible for freeing the trampoline
100 */
101 trampoline=malloc(sizeof(*trampoline));
102 trampoline->start_address = start_address;
103 trampoline->arglist = arglist;
104
105 /* FIXME */
106 return (unsigned long)CreateThread(NULL, stack_size, _beginthread_trampoline,
107 trampoline, 0, NULL);
108 }