Set %fs and %gs in the register context to their current value when
[wine] / dlls / kernel / 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 <stdarg.h>
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_TIMES_H
29 #include <sys/times.h>
30 #endif
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34
35 #include "ntstatus.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
39 #include "winnls.h"
40 #include "module.h"
41 #include "thread.h"
42 #include "wine/winbase16.h"
43 #include "wine/library.h"
44 #include "wine/server.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(thread);
48 WINE_DECLARE_DEBUG_CHANNEL(relay);
49
50
51 /***********************************************************************
52  *           THREAD_InitStack
53  *
54  * Allocate the stack of a thread.
55  */
56 TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
57 {
58     DWORD old_prot;
59     DWORD page_size = getpagesize();
60     void *base;
61
62     stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
63
64     if (!(base = VirtualAlloc( NULL, stack_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
65         return NULL;
66
67     teb->DeallocationStack = base;
68     teb->Tib.StackBase     = (char *)base + stack_size;
69     teb->Tib.StackLimit    = base;  /* note: limit is lower than base since the stack grows down */
70
71     /* Setup guard pages */
72
73     VirtualProtect( base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
74     return teb;
75 }
76
77
78 struct new_thread_info
79 {
80     LPTHREAD_START_ROUTINE func;
81     void                  *arg;
82 };
83
84 /***********************************************************************
85  *           THREAD_Start
86  *
87  * Start execution of a newly created thread. Does not return.
88  */
89 static void CALLBACK THREAD_Start( void *ptr )
90 {
91     struct new_thread_info *info = ptr;
92     LPTHREAD_START_ROUTINE func = info->func;
93     void *arg = info->arg;
94
95     RtlFreeHeap( GetProcessHeap(), 0, info );
96
97     if (TRACE_ON(relay))
98         DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
99
100     __TRY
101     {
102         MODULE_DllThreadAttach( NULL );
103         ExitThread( func( arg ) );
104     }
105     __EXCEPT(UnhandledExceptionFilter)
106     {
107         TerminateThread( GetCurrentThread(), GetExceptionCode() );
108     }
109     __ENDTRY
110 }
111
112
113 /***********************************************************************
114  *           CreateThread   (KERNEL32.@)
115  */
116 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
117                             LPTHREAD_START_ROUTINE start, LPVOID param,
118                             DWORD flags, LPDWORD id )
119 {
120     HANDLE handle;
121     CLIENT_ID client_id;
122     NTSTATUS status;
123     SIZE_T stack_reserve = 0, stack_commit = 0;
124     struct new_thread_info *info;
125
126     if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) )))
127     {
128         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
129         return 0;
130     }
131     info->func = start;
132     info->arg  = param;
133
134     if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
135     else stack_commit = stack;
136
137     status = RtlCreateUserThread( GetCurrentProcess(), NULL, (flags & CREATE_SUSPENDED) != 0,
138                                   NULL, stack_reserve, stack_commit,
139                                   THREAD_Start, info, &handle, &client_id );
140     if (status == STATUS_SUCCESS)
141     {
142         if (id) *id = (DWORD)client_id.UniqueThread;
143         if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
144             SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
145     }
146     else
147     {
148         RtlFreeHeap( GetProcessHeap(), 0, info );
149         SetLastError( RtlNtStatusToDosError(status) );
150         handle = 0;
151     }
152     return handle;
153 }
154
155
156 /***********************************************************************
157  * OpenThread  [KERNEL32.@]   Retrieves a handle to a thread from its thread id
158  */
159 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
160 {
161     HANDLE ret = 0;
162     SERVER_START_REQ( open_thread )
163     {
164         req->tid     = dwThreadId;
165         req->access  = dwDesiredAccess;
166         req->inherit = bInheritHandle;
167         if (!wine_server_call_err( req )) ret = reply->handle;
168     }
169     SERVER_END_REQ;
170     return ret;
171 }
172
173
174 /***********************************************************************
175  * ExitThread [KERNEL32.@]  Ends a thread
176  *
177  * RETURNS
178  *    None
179  */
180 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
181 {
182     BOOL last;
183     SERVER_START_REQ( terminate_thread )
184     {
185         /* send the exit code to the server */
186         req->handle    = GetCurrentThread();
187         req->exit_code = code;
188         wine_server_call( req );
189         last = reply->last;
190     }
191     SERVER_END_REQ;
192
193     if (last)
194     {
195         LdrShutdownProcess();
196         exit( code );
197     }
198     else
199     {
200         LdrShutdownThread();
201         RtlAcquirePebLock();
202         RemoveEntryList( &NtCurrentTeb()->TlsLinks );
203         RtlReleasePebLock();
204         SYSDEPS_ExitThread( code );
205     }
206 }
207
208
209 /**********************************************************************
210  * TerminateThread [KERNEL32.@]  Terminates a thread
211  *
212  * RETURNS
213  *    Success: TRUE
214  *    Failure: FALSE
215  */
216 BOOL WINAPI TerminateThread( HANDLE handle,    /* [in] Handle to thread */
217                              DWORD exit_code)  /* [in] Exit code for thread */
218 {
219     NTSTATUS status = NtTerminateThread( handle, exit_code );
220     if (status) SetLastError( RtlNtStatusToDosError(status) );
221     return !status;
222 }
223
224
225 /***********************************************************************
226  *           FreeLibraryAndExitThread (KERNEL32.@)
227  */
228 void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
229 {
230     FreeLibrary(hLibModule);
231     ExitThread(dwExitCode);
232 }
233
234
235 /**********************************************************************
236  *              GetExitCodeThread (KERNEL32.@)
237  *
238  * Gets termination status of thread.
239  *
240  * RETURNS
241  *    Success: TRUE
242  *    Failure: FALSE
243  */
244 BOOL WINAPI GetExitCodeThread(
245     HANDLE hthread, /* [in]  Handle to thread */
246     LPDWORD exitcode) /* [out] Address to receive termination status */
247 {
248     THREAD_BASIC_INFORMATION info;
249     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
250                                                 &info, sizeof(info), NULL );
251
252     if (status)
253     {
254         SetLastError( RtlNtStatusToDosError(status) );
255         return FALSE;
256     }
257     if (exitcode) *exitcode = info.ExitStatus;
258     return TRUE;
259 }
260
261
262 /***********************************************************************
263  * SetThreadContext [KERNEL32.@]  Sets context of thread.
264  *
265  * RETURNS
266  *    Success: TRUE
267  *    Failure: FALSE
268  */
269 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
270                               const CONTEXT *context ) /* [in] Address of context structure */
271 {
272     NTSTATUS status = NtSetContextThread( handle, context );
273     if (status) SetLastError( RtlNtStatusToDosError(status) );
274     return !status;
275 }
276
277
278 /***********************************************************************
279  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
280  *
281  * RETURNS
282  *    Success: TRUE
283  *    Failure: FALSE
284  */
285 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
286                               CONTEXT *context ) /* [out] Address of context structure */
287 {
288     NTSTATUS status = NtGetContextThread( handle, context );
289     if (status) SetLastError( RtlNtStatusToDosError(status) );
290     return !status;
291 }
292
293
294 /**********************************************************************
295  * SuspendThread [KERNEL32.@]  Suspends a thread.
296  *
297  * RETURNS
298  *    Success: Previous suspend count
299  *    Failure: 0xFFFFFFFF
300  */
301 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
302 {
303     DWORD ret;
304     NTSTATUS status = NtSuspendThread( hthread, &ret );
305
306     if (status)
307     {
308         ret = ~0U;
309         SetLastError( RtlNtStatusToDosError(status) );
310     }
311     return ret;
312 }
313
314
315 /**********************************************************************
316  * ResumeThread [KERNEL32.@]  Resumes a thread.
317  *
318  * Decrements a thread's suspend count.  When count is zero, the
319  * execution of the thread is resumed.
320  *
321  * RETURNS
322  *    Success: Previous suspend count
323  *    Failure: 0xFFFFFFFF
324  *    Already running: 0
325  */
326 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
327 {
328     DWORD ret;
329     NTSTATUS status = NtResumeThread( hthread, &ret );
330
331     if (status)
332     {
333         ret = ~0U;
334         SetLastError( RtlNtStatusToDosError(status) );
335     }
336     return ret;
337 }
338
339
340 /**********************************************************************
341  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
342  *
343  * RETURNS
344  *    Success: Thread's priority level.
345  *    Failure: THREAD_PRIORITY_ERROR_RETURN
346  */
347 INT WINAPI GetThreadPriority(
348     HANDLE hthread) /* [in] Handle to thread */
349 {
350     THREAD_BASIC_INFORMATION info;
351     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
352                                                 &info, sizeof(info), NULL );
353
354     if (status)
355     {
356         SetLastError( RtlNtStatusToDosError(status) );
357         return THREAD_PRIORITY_ERROR_RETURN;
358     }
359     return info.Priority;
360 }
361
362
363 /**********************************************************************
364  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
365  *
366  * RETURNS
367  *    Success: TRUE
368  *    Failure: FALSE
369  */
370 BOOL WINAPI SetThreadPriority(
371     HANDLE hthread, /* [in] Handle to thread */
372     INT priority)   /* [in] Thread priority level */
373 {
374     BOOL ret;
375     SERVER_START_REQ( set_thread_info )
376     {
377         req->handle   = hthread;
378         req->priority = priority;
379         req->mask     = SET_THREAD_INFO_PRIORITY;
380         ret = !wine_server_call_err( req );
381     }
382     SERVER_END_REQ;
383     return ret;
384 }
385
386
387 /**********************************************************************
388  * GetThreadPriorityBoost [KERNEL32.@]  Returns priority boost for thread.
389  *
390  * Always reports that priority boost is disabled.
391  *
392  * RETURNS
393  *    Success: TRUE.
394  *    Failure: FALSE
395  */
396 BOOL WINAPI GetThreadPriorityBoost(
397     HANDLE hthread, /* [in] Handle to thread */
398     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
399 {
400     if (pstate) *pstate = FALSE;
401     return NO_ERROR;
402 }
403
404
405 /**********************************************************************
406  * SetThreadPriorityBoost [KERNEL32.@]  Sets priority boost for thread.
407  *
408  * Priority boost is not implemented. Thsi function always returns
409  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
410  *
411  * RETURNS
412  *    Always returns FALSE to indicate a failure
413  */
414 BOOL WINAPI SetThreadPriorityBoost(
415     HANDLE hthread, /* [in] Handle to thread */
416     BOOL disable)   /* [in] TRUE to disable priority boost */
417 {
418     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
419     return FALSE;
420 }
421
422
423 /**********************************************************************
424  *           SetThreadAffinityMask   (KERNEL32.@)
425  */
426 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
427 {
428     DWORD ret;
429     SERVER_START_REQ( set_thread_info )
430     {
431         req->handle   = hThread;
432         req->affinity = dwThreadAffinityMask;
433         req->mask     = SET_THREAD_INFO_AFFINITY;
434         ret = !wine_server_call_err( req );
435         /* FIXME: should return previous value */
436     }
437     SERVER_END_REQ;
438     return ret;
439 }
440
441
442 /**********************************************************************
443  * SetThreadIdealProcessor [KERNEL32.@]  Obtains timing information.
444  *
445  * RETURNS
446  *    Success: Value of last call to SetThreadIdealProcessor
447  *    Failure: -1
448  */
449 DWORD WINAPI SetThreadIdealProcessor(
450     HANDLE hThread,          /* [in] Specifies the thread of interest */
451     DWORD dwIdealProcessor)  /* [in] Specifies the new preferred processor */
452 {
453     FIXME("(%p): stub\n",hThread);
454     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
455     return -1L;
456 }
457
458
459 /* callback for QueueUserAPC */
460 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
461 {
462     PAPCFUNC func = (PAPCFUNC)arg1;
463     func( arg2 );
464 }
465
466 /***********************************************************************
467  *              QueueUserAPC  (KERNEL32.@)
468  */
469 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
470 {
471     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
472
473     if (status) SetLastError( RtlNtStatusToDosError(status) );
474     return !status;
475 }
476
477
478 /**********************************************************************
479  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
480  *
481  * RETURNS
482  *    Success: TRUE
483  *    Failure: FALSE
484  */
485 BOOL WINAPI GetThreadTimes(
486     HANDLE thread,         /* [in]  Specifies the thread of interest */
487     LPFILETIME creationtime, /* [out] When the thread was created */
488     LPFILETIME exittime,     /* [out] When the thread was destroyed */
489     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
490     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
491 {
492     BOOL ret = TRUE;
493
494     if (creationtime || exittime)
495     {
496         /* We need to do a server call to get the creation time or exit time */
497         /* This works on any thread */
498
499         SERVER_START_REQ( get_thread_info )
500         {
501             req->handle = thread;
502             req->tid_in = 0;
503             if ((ret = !wine_server_call_err( req )))
504             {
505                 if (creationtime)
506                     RtlSecondsSince1970ToTime( reply->creation_time, (LARGE_INTEGER*)creationtime );
507                 if (exittime)
508                     RtlSecondsSince1970ToTime( reply->exit_time, (LARGE_INTEGER*)exittime );
509             }
510         }
511         SERVER_END_REQ;
512     }
513     if (ret && (kerneltime || usertime))
514     {
515         /* We call times(2) for kernel time or user time */
516         /* We can only (portably) do this for the current thread */
517         if (thread == GetCurrentThread())
518         {
519             ULONGLONG time;
520             struct tms time_buf;
521             long clocks_per_sec = sysconf(_SC_CLK_TCK);
522
523             times(&time_buf);
524             if (kerneltime)
525             {
526                 time = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
527                 kerneltime->dwHighDateTime = time >> 32;
528                 kerneltime->dwLowDateTime = (DWORD)time;
529             }
530             if (usertime)
531             {
532                 time = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
533                 usertime->dwHighDateTime = time >> 32;
534                 usertime->dwLowDateTime = (DWORD)time;
535             }
536         }
537         else
538         {
539             if (kerneltime) kerneltime->dwHighDateTime = kerneltime->dwLowDateTime = 0;
540             if (usertime) usertime->dwHighDateTime = usertime->dwLowDateTime = 0;
541             FIXME("Cannot get kerneltime or usertime of other threads\n");
542         }
543     }
544     return ret;
545 }
546
547
548 /**********************************************************************
549  * VWin32_BoostThreadGroup [KERNEL.535]
550  */
551 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
552 {
553     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
554 }
555
556
557 /**********************************************************************
558  * VWin32_BoostThreadStatic [KERNEL.536]
559  */
560 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
561 {
562     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
563 }
564
565
566 /***********************************************************************
567  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
568  *
569  * RETURNS
570  *    Pseudohandle for the current thread
571  */
572 #undef GetCurrentThread
573 HANDLE WINAPI GetCurrentThread(void)
574 {
575     return (HANDLE)0xfffffffe;
576 }
577
578
579 #ifdef __i386__
580
581 /***********************************************************************
582  *              SetLastError (KERNEL.147)
583  *              SetLastError (KERNEL32.@)
584  */
585 /* void WINAPI SetLastError( DWORD error ); */
586 __ASM_GLOBAL_FUNC( SetLastError,
587                    "movl 4(%esp),%eax\n\t"
588                    ".byte 0x64\n\t"
589                    "movl %eax,0x60\n\t"
590                    "ret $4" );
591
592 /***********************************************************************
593  *              GetLastError (KERNEL.148)
594  *              GetLastError (KERNEL32.@)
595  */
596 /* DWORD WINAPI GetLastError(void); */
597 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x60,%eax\n\tret" );
598
599 /***********************************************************************
600  *              GetCurrentProcessId (KERNEL.471)
601  *              GetCurrentProcessId (KERNEL32.@)
602  */
603 /* DWORD WINAPI GetCurrentProcessId(void) */
604 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" );
605
606 /***********************************************************************
607  *              GetCurrentThreadId (KERNEL.462)
608  *              GetCurrentThreadId (KERNEL32.@)
609  */
610 /* DWORD WINAPI GetCurrentThreadId(void) */
611 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" );
612
613 #else  /* __i386__ */
614
615 /**********************************************************************
616  *              SetLastError (KERNEL.147)
617  *              SetLastError (KERNEL32.@)
618  *
619  * Sets the last-error code.
620  */
621 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
622 {
623     NtCurrentTeb()->last_error = error;
624 }
625
626 /**********************************************************************
627  *              GetLastError (KERNEL.148)
628  *              GetLastError (KERNEL32.@)
629  *
630  * Returns last-error code.
631  */
632 DWORD WINAPI GetLastError(void)
633 {
634     return NtCurrentTeb()->last_error;
635 }
636
637 /***********************************************************************
638  *              GetCurrentProcessId (KERNEL.471)
639  *              GetCurrentProcessId (KERNEL32.@)
640  *
641  * Returns process identifier.
642  */
643 DWORD WINAPI GetCurrentProcessId(void)
644 {
645     return (DWORD)NtCurrentTeb()->ClientId.UniqueProcess;
646 }
647
648 /***********************************************************************
649  *              GetCurrentThreadId (KERNEL.462)
650  *              GetCurrentThreadId (KERNEL32.@)
651  *
652  * Returns thread identifier.
653  */
654 DWORD WINAPI GetCurrentThreadId(void)
655 {
656     return (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
657 }
658
659 #endif  /* __i386__ */