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