3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/thread/thread.c
6 * PURPOSE: Thread functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * Tls functions are modified from WINE
13 /* INCLUDES ******************************************************************/
18 #include <kernel32/kernel32.h>
21 //static VOID ThreadAttachDlls (VOID);
23 /* FUNCTIONS *****************************************************************/
25 static EXCEPTION_DISPOSITION __cdecl
26 _except_handler(struct _EXCEPTION_RECORD *ExceptionRecord,
27 void * EstablisherFrame,
28 struct _CONTEXT *ContextRecord,
29 void * DispatcherContext)
33 /* We should not get to here */
34 return(ExceptionContinueSearch);
39 ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
44 __try1(_except_handler)
46 /* FIXME: notify csrss of thread creation ?? */
47 uExitCode = (lpStartAddress)(lpParameter);
53 ExitThread(uExitCode);
58 CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
60 LPTHREAD_START_ROUTINE lpStartAddress,
62 DWORD dwCreationFlags,
65 return(CreateRemoteThread(NtCurrentProcess(),
76 CreateRemoteThread(HANDLE hProcess,
77 LPSECURITY_ATTRIBUTES lpThreadAttributes,
79 LPTHREAD_START_ROUTINE lpStartAddress,
81 DWORD dwCreationFlags,
85 OBJECT_ATTRIBUTES ObjectAttributes;
87 CONTEXT ThreadContext;
88 INITIAL_TEB InitialTeb;
89 BOOLEAN CreateSuspended = FALSE;
91 ULONG OldPageProtection;
94 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
95 ObjectAttributes.RootDirectory = NULL;
96 ObjectAttributes.ObjectName = NULL;
97 ObjectAttributes.Attributes = 0;
98 if (lpThreadAttributes != NULL)
100 if (lpThreadAttributes->bInheritHandle)
101 ObjectAttributes.Attributes = OBJ_INHERIT;
102 ObjectAttributes.SecurityDescriptor =
103 lpThreadAttributes->lpSecurityDescriptor;
105 ObjectAttributes.SecurityQualityOfService = NULL;
107 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
108 CreateSuspended = TRUE;
110 CreateSuspended = FALSE;
112 InitialTeb.StackReserve = 0x100000; /* 1MByte */
113 /* FIXME: use correct commit size */
115 InitialTeb.StackCommit = (dwStackSize == 0) ? PAGE_SIZE : dwStackSize;
117 InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
119 /* size of guard page */
120 InitialTeb.StackCommit += PAGE_SIZE;
123 InitialTeb.StackAllocate = NULL;
124 Status = NtAllocateVirtualMemory(hProcess,
125 &InitialTeb.StackAllocate,
127 &InitialTeb.StackReserve,
130 if (!NT_SUCCESS(Status))
132 DPRINT("Error reserving stack space!\n");
133 SetLastErrorByStatus(Status);
137 DPRINT("StackDeallocation: %p ReserveSize: 0x%lX\n",
138 InitialTeb.StackDeallocation, InitialTeb.StackReserve);
140 InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
141 InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
143 DPRINT("StackBase: %p\nStackCommit: 0x%lX\n",
144 InitialTeb.StackBase,
145 InitialTeb.StackCommit);
147 /* Commit stack pages */
148 Status = NtAllocateVirtualMemory(hProcess,
149 &InitialTeb.StackLimit,
151 &InitialTeb.StackCommit,
154 if (!NT_SUCCESS(Status))
156 /* release the stack space */
157 NtFreeVirtualMemory(hProcess,
158 InitialTeb.StackAllocate,
159 &InitialTeb.StackReserve,
162 DPRINT("Error comitting stack page(s)!\n");
163 SetLastErrorByStatus(Status);
167 DPRINT("StackLimit: %p\n",
168 InitialTeb.StackLimit);
170 /* Protect guard page */
171 Status = NtProtectVirtualMemory(hProcess,
172 InitialTeb.StackLimit,
174 PAGE_GUARD | PAGE_READWRITE,
176 if (!NT_SUCCESS(Status))
178 /* release the stack space */
179 NtFreeVirtualMemory(hProcess,
180 InitialTeb.StackAllocate,
181 &InitialTeb.StackReserve,
184 DPRINT("Error comitting guard page!\n");
185 SetLastErrorByStatus(Status);
189 memset(&ThreadContext,0,sizeof(CONTEXT));
190 ThreadContext.Eip = (LONG)ThreadStartup;
191 ThreadContext.SegGs = USER_DS;
192 ThreadContext.SegFs = TEB_SELECTOR;
193 ThreadContext.SegEs = USER_DS;
194 ThreadContext.SegDs = USER_DS;
195 ThreadContext.SegCs = USER_CS;
196 ThreadContext.SegSs = USER_DS;
197 ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 12;
198 ThreadContext.EFlags = (1<<1) + (1<<9);
200 /* initialize call stack */
201 *((PULONG)((ULONG)InitialTeb.StackBase - 4)) = (ULONG)lpParameter;
202 *((PULONG)((ULONG)InitialTeb.StackBase - 8)) = (ULONG)lpStartAddress;
203 *((PULONG)((ULONG)InitialTeb.StackBase - 12)) = 0xdeadbeef;
205 DPRINT("Esp: %p\n", ThreadContext.Esp);
206 DPRINT("Eip: %p\n", ThreadContext.Eip);
208 Status = NtCreateThread(&ThreadHandle,
216 if (!NT_SUCCESS(Status))
218 NtFreeVirtualMemory(hProcess,
219 InitialTeb.StackAllocate,
220 &InitialTeb.StackReserve,
223 DPRINT("NtCreateThread() failed!\n");
224 SetLastErrorByStatus(Status);
228 if (lpThreadId != NULL)
229 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
231 return(ThreadHandle);
238 return(NtCurrentTeb());
246 errCode = NtYieldExecution();
252 GetCurrentThreadId(VOID)
254 return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
259 ExitThread(DWORD uExitCode)
265 * Terminate process if this is the last thread
266 * of the current process
268 Status = NtQueryInformationThread(NtCurrentThread(),
273 if (NT_SUCCESS(Status) && LastThread == TRUE)
275 ExitProcess(uExitCode);
278 /* FIXME: notify csrss of thread termination */
282 Status = NtTerminateThread(NtCurrentThread(),
284 if (!NT_SUCCESS(Status))
286 SetLastErrorByStatus(Status);
292 GetThreadTimes(HANDLE hThread,
293 LPFILETIME lpCreationTime,
294 LPFILETIME lpExitTime,
295 LPFILETIME lpKernelTime,
296 LPFILETIME lpUserTime)
298 KERNEL_USER_TIMES KernelUserTimes;
302 Status = NtQueryInformationThread(hThread,
305 sizeof(KERNEL_USER_TIMES),
307 if (!NT_SUCCESS(Status))
309 SetLastErrorByStatus(Status);
313 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
314 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
315 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
316 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
323 GetThreadContext(HANDLE hThread,
328 Status = NtGetContextThread(hThread,
330 if (!NT_SUCCESS(Status))
332 SetLastErrorByStatus(Status);
341 SetThreadContext(HANDLE hThread,
342 CONST CONTEXT *lpContext)
346 Status = NtSetContextThread(hThread,
348 if (!NT_SUCCESS(Status))
350 SetLastErrorByStatus(Status);
359 GetExitCodeThread(HANDLE hThread,
362 THREAD_BASIC_INFORMATION ThreadBasic;
366 Status = NtQueryInformationThread(hThread,
367 ThreadBasicInformation,
369 sizeof(THREAD_BASIC_INFORMATION),
371 if (!NT_SUCCESS(Status))
373 SetLastErrorByStatus(Status);
377 memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
384 ResumeThread(HANDLE hThread)
386 ULONG PreviousResumeCount;
389 Status = NtResumeThread(hThread,
390 &PreviousResumeCount);
391 if (!NT_SUCCESS(Status))
393 SetLastErrorByStatus(Status);
397 return(PreviousResumeCount);
402 TerminateThread(HANDLE hThread,
409 SetLastError(ERROR_INVALID_HANDLE);
413 Status = NtTerminateThread(hThread,
415 if (!NT_SUCCESS(Status))
417 SetLastErrorByStatus(Status);
426 SuspendThread(HANDLE hThread)
428 ULONG PreviousSuspendCount;
431 Status = NtSuspendThread(hThread,
432 &PreviousSuspendCount);
433 if (!NT_SUCCESS(Status))
435 SetLastErrorByStatus(Status);
439 return(PreviousSuspendCount);
444 SetThreadAffinityMask(HANDLE hThread,
445 DWORD dwThreadAffinityMask)
447 THREAD_BASIC_INFORMATION ThreadBasic;
448 KAFFINITY AffinityMask;
452 AffinityMask = (KAFFINITY)dwThreadAffinityMask;
454 Status = NtQueryInformationThread(hThread,
455 ThreadBasicInformation,
457 sizeof(THREAD_BASIC_INFORMATION),
459 if (!NT_SUCCESS(Status))
461 SetLastErrorByStatus(Status);
465 Status = NtSetInformationThread(hThread,
469 if (!NT_SUCCESS(Status))
470 SetLastErrorByStatus(Status);
472 return(ThreadBasic.AffinityMask);
477 SetThreadPriority(HANDLE hThread,
480 THREAD_BASIC_INFORMATION ThreadBasic;
484 Status = NtQueryInformationThread(hThread,
485 ThreadBasicInformation,
487 sizeof(THREAD_BASIC_INFORMATION),
489 if (!NT_SUCCESS(Status))
491 SetLastErrorByStatus(Status);
495 ThreadBasic.BasePriority = nPriority;
497 Status = NtSetInformationThread(hThread,
498 ThreadBasicInformation,
500 sizeof(THREAD_BASIC_INFORMATION));
501 if (!NT_SUCCESS(Status))
503 SetLastErrorByStatus(Status);
512 GetThreadPriority(HANDLE hThread)
514 THREAD_BASIC_INFORMATION ThreadBasic;
518 Status = NtQueryInformationThread(hThread,
519 ThreadBasicInformation,
521 sizeof(THREAD_BASIC_INFORMATION),
523 if (!NT_SUCCESS(Status))
525 SetLastErrorByStatus(Status);
526 return(THREAD_PRIORITY_ERROR_RETURN);
529 return(ThreadBasic.BasePriority);
534 GetThreadPriorityBoost(IN HANDLE hThread,
535 OUT PBOOL pDisablePriorityBoost)
541 Status = NtQueryInformationThread(hThread,
546 if (!NT_SUCCESS(Status))
548 SetLastErrorByStatus(Status);
552 *pDisablePriorityBoost = !((WINBOOL)PriorityBoost);
559 SetThreadPriorityBoost(IN HANDLE hThread,
560 IN WINBOOL bDisablePriorityBoost)
565 PriorityBoost = (ULONG)!bDisablePriorityBoost;
567 Status = NtSetInformationThread(hThread,
571 if (!NT_SUCCESS(Status))
573 SetLastErrorByStatus(Status);
582 GetThreadSelectorEntry(IN HANDLE hThread,
584 OUT LPLDT_ENTRY lpSelectorEntry)
586 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
592 SetThreadIdealProcessor(HANDLE hThread,
593 DWORD dwIdealProcessor)
595 ULONG IdealProcessor;
598 IdealProcessor = (ULONG)dwIdealProcessor;
600 Status = NtSetInformationThread(hThread,
601 ThreadIdealProcessor,
604 if (!NT_SUCCESS(Status))
606 SetLastErrorByStatus(Status);