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