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