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>
20 //static VOID ThreadAttachDlls (VOID);
22 /* FUNCTIONS *****************************************************************/
24 /* FIXME: please put this in some header */
25 static EXCEPTION_DISPOSITION __cdecl
26 _except_handler(EXCEPTION_RECORD *ExceptionRecord,
27 void * EstablisherFrame,
28 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);
57 HANDLE STDCALL CreateThread
59 LPSECURITY_ATTRIBUTES lpThreadAttributes,
61 LPTHREAD_START_ROUTINE lpStartAddress,
63 DWORD dwCreationFlags,
67 return CreateRemoteThread
80 HANDLE STDCALL CreateRemoteThread
83 LPSECURITY_ATTRIBUTES lpThreadAttributes,
85 LPTHREAD_START_ROUTINE lpStartAddress,
87 DWORD dwCreationFlags,
91 PSECURITY_DESCRIPTOR pSD = NULL;
93 CLIENT_ID cidClientId;
95 ULONG_PTR nStackReserve;
96 ULONG_PTR nStackCommit;
97 OBJECT_ATTRIBUTES oaThreadAttribs;
98 PIMAGE_NT_HEADERS pinhHeader =
99 RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
104 "lpThreadAttributes %08X\n"
106 "lpStartAddress %08X\n"
108 "dwCreationFlags %08X\n"
119 /* FIXME: do more checks - e.g. the image may not have an optional header */
120 if(pinhHeader == NULL)
122 nStackReserve = 0x100000;
123 nStackCommit = PAGE_SIZE;
127 nStackReserve = pinhHeader->OptionalHeader.SizeOfStackReserve;
128 nStackCommit = pinhHeader->OptionalHeader.SizeOfStackCommit;
131 /* FIXME: this should be defined in winbase.h */
132 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
133 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
137 if(dwStackSize == 0);
138 /* dwStackSize specifies the size to reserve */
139 else if(dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION)
140 nStackReserve = dwStackSize;
141 /* dwStackSize specifies the size to commit */
143 nStackCommit = dwStackSize;
145 /* fix the stack reserve size */
146 if(nStackCommit > nStackReserve)
147 nStackReserve = ROUNDUP(nStackCommit, 0x100000);
149 /* initialize the attributes for the thread object */
150 InitializeObjectAttributes
159 if(lpThreadAttributes)
161 /* make the handle inheritable */
162 if(lpThreadAttributes->bInheritHandle)
163 oaThreadAttribs.Attributes |= OBJ_INHERIT;
165 /* user-defined security descriptor */
166 oaThreadAttribs.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
171 "RtlRosCreateUserThreadVa\n"
173 " ProcessHandle %p,\n"
174 " ObjectAttributes %p,\n"
175 " CreateSuspended %d,\n"
176 " StackZeroBits %d,\n"
177 " StackReserve %lu,\n"
178 " StackCommit %lu,\n"
179 " StartAddress %p,\n"
180 " ThreadHandle %p,\n"
182 " ParameterCount %u,\n"
183 " Parameters[0] %p,\n"
184 " Parameters[1] %p\n"
188 dwCreationFlags & CREATE_SUSPENDED,
200 /* create the thread */
201 nErrCode = RtlRosCreateUserThreadVa
205 dwCreationFlags & CREATE_SUSPENDED,
209 (PTHREAD_START_ROUTINE)ThreadStartup,
218 if(!NT_SUCCESS(nErrCode))
220 SetLastErrorByStatus(nErrCode);
229 "ClientId.UniqueThread %p\n",
233 cidClientId.UniqueThread
237 if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
244 return(NtCurrentTeb());
252 errCode = NtYieldExecution();
258 GetCurrentThreadId(VOID)
260 return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
265 ExitThread(DWORD uExitCode)
271 * Terminate process if this is the last thread
272 * of the current process
274 Status = NtQueryInformationThread(NtCurrentThread(),
279 if (NT_SUCCESS(Status) && LastThread == TRUE)
281 ExitProcess(uExitCode);
284 /* FIXME: notify csrss of thread termination */
288 Status = NtTerminateThread(NtCurrentThread(),
290 if (!NT_SUCCESS(Status))
292 SetLastErrorByStatus(Status);
298 GetThreadTimes(HANDLE hThread,
299 LPFILETIME lpCreationTime,
300 LPFILETIME lpExitTime,
301 LPFILETIME lpKernelTime,
302 LPFILETIME lpUserTime)
304 KERNEL_USER_TIMES KernelUserTimes;
308 Status = NtQueryInformationThread(hThread,
311 sizeof(KERNEL_USER_TIMES),
313 if (!NT_SUCCESS(Status))
315 SetLastErrorByStatus(Status);
319 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
320 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
321 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
322 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
329 GetThreadContext(HANDLE hThread,
334 Status = NtGetContextThread(hThread,
336 if (!NT_SUCCESS(Status))
338 SetLastErrorByStatus(Status);
347 SetThreadContext(HANDLE hThread,
348 CONST CONTEXT *lpContext)
352 Status = NtSetContextThread(hThread,
354 if (!NT_SUCCESS(Status))
356 SetLastErrorByStatus(Status);
365 GetExitCodeThread(HANDLE hThread,
368 THREAD_BASIC_INFORMATION ThreadBasic;
372 Status = NtQueryInformationThread(hThread,
373 ThreadBasicInformation,
375 sizeof(THREAD_BASIC_INFORMATION),
377 if (!NT_SUCCESS(Status))
379 SetLastErrorByStatus(Status);
383 memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
390 ResumeThread(HANDLE hThread)
392 ULONG PreviousResumeCount;
395 Status = NtResumeThread(hThread,
396 &PreviousResumeCount);
397 if (!NT_SUCCESS(Status))
399 SetLastErrorByStatus(Status);
403 return(PreviousResumeCount);
408 TerminateThread(HANDLE hThread,
415 SetLastError(ERROR_INVALID_HANDLE);
419 Status = NtTerminateThread(hThread,
421 if (!NT_SUCCESS(Status))
423 SetLastErrorByStatus(Status);
432 SuspendThread(HANDLE hThread)
434 ULONG PreviousSuspendCount;
437 Status = NtSuspendThread(hThread,
438 &PreviousSuspendCount);
439 if (!NT_SUCCESS(Status))
441 SetLastErrorByStatus(Status);
445 return(PreviousSuspendCount);
450 SetThreadAffinityMask(HANDLE hThread,
451 DWORD dwThreadAffinityMask)
453 THREAD_BASIC_INFORMATION ThreadBasic;
454 KAFFINITY AffinityMask;
458 AffinityMask = (KAFFINITY)dwThreadAffinityMask;
460 Status = NtQueryInformationThread(hThread,
461 ThreadBasicInformation,
463 sizeof(THREAD_BASIC_INFORMATION),
465 if (!NT_SUCCESS(Status))
467 SetLastErrorByStatus(Status);
471 Status = NtSetInformationThread(hThread,
475 if (!NT_SUCCESS(Status))
476 SetLastErrorByStatus(Status);
478 return(ThreadBasic.AffinityMask);
483 SetThreadPriority(HANDLE hThread,
486 ULONG Prio = nPriority;
489 Status = NtSetInformationThread(hThread,
494 if (!NT_SUCCESS(Status))
496 SetLastErrorByStatus(Status);
505 GetThreadPriority(HANDLE hThread)
507 THREAD_BASIC_INFORMATION ThreadBasic;
511 Status = NtQueryInformationThread(hThread,
512 ThreadBasicInformation,
514 sizeof(THREAD_BASIC_INFORMATION),
516 if (!NT_SUCCESS(Status))
518 SetLastErrorByStatus(Status);
519 return(THREAD_PRIORITY_ERROR_RETURN);
522 return(ThreadBasic.BasePriority);
527 GetThreadPriorityBoost(IN HANDLE hThread,
528 OUT PBOOL pDisablePriorityBoost)
534 Status = NtQueryInformationThread(hThread,
539 if (!NT_SUCCESS(Status))
541 SetLastErrorByStatus(Status);
545 *pDisablePriorityBoost = !((WINBOOL)PriorityBoost);
552 SetThreadPriorityBoost(IN HANDLE hThread,
553 IN WINBOOL bDisablePriorityBoost)
558 PriorityBoost = (ULONG)!bDisablePriorityBoost;
560 Status = NtSetInformationThread(hThread,
564 if (!NT_SUCCESS(Status))
566 SetLastErrorByStatus(Status);
575 GetThreadSelectorEntry(IN HANDLE hThread,
577 OUT LPLDT_ENTRY lpSelectorEntry)
579 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
585 SetThreadIdealProcessor(HANDLE hThread,
586 DWORD dwIdealProcessor)
588 ULONG IdealProcessor;
591 IdealProcessor = (ULONG)dwIdealProcessor;
593 Status = NtSetInformationThread(hThread,
594 ThreadIdealProcessor,
597 if (!NT_SUCCESS(Status))
599 SetLastErrorByStatus(Status);