Fix the case of product and company names.
[wine] / scheduler / thread.c
1 /*
2  * Win32 threads
3  *
4  * Copyright 1996 Alexandre Julliard
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 "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_MMAN_H
28 #include <sys/mman.h>
29 #endif
30 #ifdef HAVE_SYS_TIMES_H
31 #include <sys/times.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #include "wine/winbase16.h"
37 #include "ntstatus.h"
38 #include "thread.h"
39 #include "module.h"
40 #include "winerror.h"
41 #include "selectors.h"
42 #include "winnt.h"
43 #include "wine/server.h"
44 #include "wine/debug.h"
45 #include "winnls.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(thread);
48 WINE_DECLARE_DEBUG_CHANNEL(relay);
49
50 /* TEB of the initial thread */
51 static TEB initial_teb;
52
53 extern struct _PDB current_process;
54
55 /***********************************************************************
56  *           THREAD_InitTEB
57  *
58  * Initialization of a newly created TEB.
59  */
60 static BOOL THREAD_InitTEB( TEB *teb )
61 {
62     teb->Tib.ExceptionList = (void *)~0UL;
63     teb->Tib.StackBase     = (void *)~0UL;
64     teb->Tib.Self          = &teb->Tib;
65     teb->tibflags  = TEBF_WIN32;
66     teb->exit_code = STILL_ACTIVE;
67     teb->request_fd = -1;
68     teb->reply_fd   = -1;
69     teb->wait_fd[0] = -1;
70     teb->wait_fd[1] = -1;
71     teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
72     teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
73     InitializeListHead(&teb->TlsLinks);
74     teb->teb_sel = wine_ldt_alloc_fs();
75     return (teb->teb_sel != 0);
76 }
77
78
79 /***********************************************************************
80  *           THREAD_FreeTEB
81  *
82  * Free data structures associated with a thread.
83  * Must be called from the context of another thread.
84  */
85 static void THREAD_FreeTEB( TEB *teb )
86 {
87     TRACE("(%p) called\n", teb );
88     /* Free the associated memory */
89     wine_ldt_free_fs( teb->teb_sel );
90     VirtualFree( teb->DeallocationStack, 0, MEM_RELEASE );
91 }
92
93
94 /***********************************************************************
95  *           THREAD_InitStack
96  *
97  * Allocate the stack of a thread.
98  */
99 TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
100 {
101     DWORD old_prot, total_size;
102     DWORD page_size = getpagesize();
103     void *base;
104
105     /* Allocate the stack */
106
107     if (stack_size >= 16*1024*1024)
108         WARN("Thread stack size is %ld MB.\n",stack_size/1024/1024);
109
110     /* if size is smaller than default, get stack size from parent */
111     if (stack_size < 1024 * 1024)
112     {
113         if (teb)
114             stack_size = 1024 * 1024;  /* no parent */
115         else
116             stack_size = ((char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->DeallocationStack
117                           - SIGNAL_STACK_SIZE - 3 * page_size);
118     }
119
120     /* FIXME: some Wine functions use a lot of stack, so we add 64Kb here */
121     stack_size += 64 * 1024;
122
123     /* Memory layout in allocated block:
124      *
125      *   size                 contents
126      * 1 page              NOACCESS guard page
127      * SIGNAL_STACK_SIZE   signal stack
128      * 1 page              NOACCESS guard page
129      * 1 page              PAGE_GUARD guard page
130      * stack_size          normal stack
131      * 1 page              TEB (except for initial thread)
132      */
133
134     stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
135     total_size = stack_size + SIGNAL_STACK_SIZE + 3 * page_size;
136     if (!teb) total_size += page_size;
137
138     if (!(base = VirtualAlloc( NULL, total_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
139         return NULL;
140
141     if (!teb)
142     {
143         teb = (TEB *)((char *)base + total_size - page_size);
144         if (!THREAD_InitTEB( teb ))
145         {
146             VirtualFree( base, 0, MEM_RELEASE );
147             return NULL;
148         }
149     }
150
151     teb->DeallocationStack = base;
152     teb->signal_stack      = (char *)base + page_size;
153     teb->Tib.StackBase     = (char *)base + 3 * page_size + SIGNAL_STACK_SIZE + stack_size;
154     teb->Tib.StackLimit    = base;  /* note: limit is lower than base since the stack grows down */
155
156     /* Setup guard pages */
157
158     VirtualProtect( base, 1, PAGE_NOACCESS, &old_prot );
159     VirtualProtect( (char *)teb->signal_stack + SIGNAL_STACK_SIZE, 1, PAGE_NOACCESS, &old_prot );
160     VirtualProtect( (char *)teb->signal_stack + SIGNAL_STACK_SIZE + page_size, 1,
161                     PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
162     return teb;
163 }
164
165
166 /***********************************************************************
167  *           THREAD_Init
168  *
169  * Setup the initial thread.
170  *
171  * NOTES: The first allocated TEB on NT is at 0x7ffde000.
172  */
173 void THREAD_Init(void)
174 {
175     static struct debug_info info;  /* debug info for initial thread */
176
177     if (!initial_teb.Tib.Self)  /* do it only once */
178     {
179         THREAD_InitTEB( &initial_teb );
180         assert( initial_teb.teb_sel );
181         info.str_pos = info.strings;
182         info.out_pos = info.output;
183         initial_teb.debug_info = &info;
184         initial_teb.Peb = (PEB *)&current_process;  /* FIXME */
185         SYSDEPS_SetCurThread( &initial_teb );
186     }
187 }
188
189 DECL_GLOBAL_CONSTRUCTOR(thread_init) { THREAD_Init(); }
190
191
192 /***********************************************************************
193  *           THREAD_Start
194  *
195  * Start execution of a newly created thread. Does not return.
196  */
197 static void THREAD_Start( TEB *teb )
198 {
199     LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)teb->entry_point;
200     struct debug_info info;
201
202     info.str_pos = info.strings;
203     info.out_pos = info.output;
204     teb->debug_info = &info;
205
206     SYSDEPS_SetCurThread( teb );
207     SIGNAL_Init();
208     CLIENT_InitThread();
209
210     if (TRACE_ON(relay))
211         DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
212
213     __TRY
214     {
215         MODULE_DllThreadAttach( NULL );
216         ExitThread( func( NtCurrentTeb()->entry_arg ) );
217     }
218     __EXCEPT(UnhandledExceptionFilter)
219     {
220         TerminateThread( GetCurrentThread(), GetExceptionCode() );
221     }
222     __ENDTRY
223 }
224
225
226 /***********************************************************************
227  *           CreateThread   (KERNEL32.@)
228  */
229 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
230                             LPTHREAD_START_ROUTINE start, LPVOID param,
231                             DWORD flags, LPDWORD id )
232 {
233     HANDLE handle = 0;
234     TEB *teb;
235     DWORD tid = 0;
236     int request_pipe[2];
237
238     if (pipe( request_pipe ) == -1)
239     {
240         SetLastError( ERROR_TOO_MANY_OPEN_FILES );
241         return 0;
242     }
243     fcntl( request_pipe[1], F_SETFD, 1 ); /* set close on exec flag */
244     wine_server_send_fd( request_pipe[0] );
245
246     SERVER_START_REQ( new_thread )
247     {
248         req->suspend    = ((flags & CREATE_SUSPENDED) != 0);
249         req->inherit    = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
250         req->request_fd = request_pipe[0];
251         if (!wine_server_call_err( req ))
252         {
253             handle = reply->handle;
254             tid = reply->tid;
255         }
256         close( request_pipe[0] );
257     }
258     SERVER_END_REQ;
259
260     if (!handle || !(teb = THREAD_InitStack( NULL, stack )))
261     {
262         close( request_pipe[1] );
263         return 0;
264     }
265
266     teb->Peb         = NtCurrentTeb()->Peb;
267     teb->ClientId.UniqueThread = (HANDLE)tid;
268     teb->request_fd  = request_pipe[1];
269     teb->entry_point = start;
270     teb->entry_arg   = param;
271     teb->htask16     = GetCurrentTask();
272     RtlAcquirePebLock();
273     InsertHeadList( &NtCurrentTeb()->TlsLinks, &teb->TlsLinks );
274     RtlReleasePebLock();
275
276     if (id) *id = tid;
277     if (SYSDEPS_SpawnThread( THREAD_Start, teb ) == -1)
278     {
279         CloseHandle( handle );
280         close( request_pipe[1] );
281         RtlAcquirePebLock();
282         RemoveEntryList( &teb->TlsLinks );
283         RtlReleasePebLock();
284         THREAD_FreeTEB( teb );
285         return 0;
286     }
287     return handle;
288 }
289
290 /***********************************************************************
291  * ExitThread [KERNEL32.@]  Ends a thread
292  *
293  * RETURNS
294  *    None
295  */
296 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
297 {
298     BOOL last;
299     SERVER_START_REQ( terminate_thread )
300     {
301         /* send the exit code to the server */
302         req->handle    = GetCurrentThread();
303         req->exit_code = code;
304         wine_server_call( req );
305         last = reply->last;
306     }
307     SERVER_END_REQ;
308
309     if (last)
310     {
311         LdrShutdownProcess();
312         exit( code );
313     }
314     else
315     {
316         LdrShutdownThread();
317         RtlAcquirePebLock();
318         RemoveEntryList( &NtCurrentTeb()->TlsLinks );
319         RtlReleasePebLock();
320         SYSDEPS_ExitThread( code );
321     }
322 }
323
324 /***********************************************************************
325  * OpenThread Retrieves a handle to a thread from its thread id
326  *
327  * RETURNS
328  *    None
329  */
330 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
331 {
332     HANDLE ret = 0;
333     SERVER_START_REQ( open_thread )
334     {
335         req->tid     = dwThreadId;
336         req->access  = dwDesiredAccess;
337         req->inherit = bInheritHandle;
338         if (!wine_server_call_err( req )) ret = reply->handle;
339     }
340     SERVER_END_REQ;
341     return ret;
342 }
343
344 /**********************************************************************
345  * TerminateThread [KERNEL32.@]  Terminates a thread
346  *
347  * RETURNS
348  *    Success: TRUE
349  *    Failure: FALSE
350  */
351 BOOL WINAPI TerminateThread( HANDLE handle,    /* [in] Handle to thread */
352                              DWORD exit_code)  /* [in] Exit code for thread */
353 {
354     NTSTATUS status = NtTerminateThread( handle, exit_code );
355     if (status) SetLastError( RtlNtStatusToDosError(status) );
356     return !status;
357 }
358
359
360 /**********************************************************************
361  *              GetExitCodeThread (KERNEL32.@)
362  *
363  * Gets termination status of thread.
364  *
365  * RETURNS
366  *    Success: TRUE
367  *    Failure: FALSE
368  */
369 BOOL WINAPI GetExitCodeThread(
370     HANDLE hthread, /* [in]  Handle to thread */
371     LPDWORD exitcode) /* [out] Address to receive termination status */
372 {
373     THREAD_BASIC_INFORMATION info;
374     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
375                                                 &info, sizeof(info), NULL );
376
377     if (status)
378     {
379         SetLastError( RtlNtStatusToDosError(status) );
380         return FALSE;
381     }
382     if (exitcode) *exitcode = info.ExitStatus;
383     return TRUE;
384 }
385
386
387 /* callback for QueueUserAPC */
388 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
389 {
390     PAPCFUNC func = (PAPCFUNC)arg1;
391     func( arg2 );
392 }
393
394 /***********************************************************************
395  *              QueueUserAPC  (KERNEL32.@)
396  */
397 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
398 {
399     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
400
401     if (status) SetLastError( RtlNtStatusToDosError(status) );
402     return !status;
403 }
404
405
406 /***********************************************************************
407  * ProcessIdToSessionId   (KERNEL32.@)
408  * This function is available on Terminal Server 4SP4 and Windows 2000
409  */
410 BOOL WINAPI ProcessIdToSessionId( DWORD procid, DWORD *sessionid_ptr )
411 {
412         /* According to MSDN, if the calling process is not in a terminal
413          * services environment, then the sessionid returned is zero.
414          */
415         *sessionid_ptr = 0;
416         return TRUE;
417 }
418
419
420 #ifdef __i386__
421
422 /***********************************************************************
423  *              SetLastError (KERNEL.147)
424  *              SetLastError (KERNEL32.@)
425  */
426 /* void WINAPI SetLastError( DWORD error ); */
427 __ASM_GLOBAL_FUNC( SetLastError,
428                    "movl 4(%esp),%eax\n\t"
429                    ".byte 0x64\n\t"
430                    "movl %eax,0x60\n\t"
431                    "ret $4" );
432
433 /***********************************************************************
434  *              GetLastError (KERNEL.148)
435  *              GetLastError (KERNEL32.@)
436  */
437 /* DWORD WINAPI GetLastError(void); */
438 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x60,%eax\n\tret" );
439
440 /***********************************************************************
441  *              GetCurrentProcessId (KERNEL.471)
442  *              GetCurrentProcessId (KERNEL32.@)
443  */
444 /* DWORD WINAPI GetCurrentProcessId(void) */
445 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" );
446
447 /***********************************************************************
448  *              GetCurrentThreadId (KERNEL.462)
449  *              GetCurrentThreadId (KERNEL32.@)
450  */
451 /* DWORD WINAPI GetCurrentThreadId(void) */
452 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" );
453
454 #else  /* __i386__ */
455
456 /**********************************************************************
457  *              SetLastError (KERNEL.147)
458  *              SetLastError (KERNEL32.@)
459  *
460  * Sets the last-error code.
461  */
462 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
463 {
464     NtCurrentTeb()->last_error = error;
465 }
466
467 /**********************************************************************
468  *              GetLastError (KERNEL.148)
469  *              GetLastError (KERNEL32.@)
470  *
471  * Returns last-error code.
472  */
473 DWORD WINAPI GetLastError(void)
474 {
475     return NtCurrentTeb()->last_error;
476 }
477
478 /***********************************************************************
479  *              GetCurrentProcessId (KERNEL.471)
480  *              GetCurrentProcessId (KERNEL32.@)
481  *
482  * Returns process identifier.
483  */
484 DWORD WINAPI GetCurrentProcessId(void)
485 {
486     return (DWORD)NtCurrentTeb()->ClientId.UniqueProcess;
487 }
488
489 /***********************************************************************
490  *              GetCurrentThreadId (KERNEL.462)
491  *              GetCurrentThreadId (KERNEL32.@)
492  *
493  * Returns thread identifier.
494  */
495 DWORD WINAPI GetCurrentThreadId(void)
496 {
497     return (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
498 }
499
500 #endif  /* __i386__ */