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);
38 __declspec(noreturn) void STDCALL
41 LPTHREAD_START_ROUTINE lpStartAddress,
45 volatile UINT uExitCode = 0;
47 __try1(_except_handler)
49 /* FIXME: notify csrss of thread creation ?? */
50 uExitCode = (lpStartAddress)(lpParameter);
56 ExitThread(uExitCode);
66 LPSECURITY_ATTRIBUTES lpThreadAttributes,
68 LPTHREAD_START_ROUTINE lpStartAddress,
70 DWORD dwCreationFlags,
74 return CreateRemoteThread
94 LPSECURITY_ATTRIBUTES lpThreadAttributes,
96 LPTHREAD_START_ROUTINE lpStartAddress,
98 DWORD dwCreationFlags,
103 CLIENT_ID cidClientId;
105 ULONG_PTR nStackReserve;
106 ULONG_PTR nStackCommit;
107 OBJECT_ATTRIBUTES oaThreadAttribs;
108 PIMAGE_NT_HEADERS pinhHeader =
109 RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
114 "lpThreadAttributes %08X\n"
116 "lpStartAddress %08X\n"
118 "dwCreationFlags %08X\n"
129 /* FIXME: do more checks - e.g. the image may not have an optional header */
130 if(pinhHeader == NULL)
132 nStackReserve = 0x100000;
133 nStackCommit = PAGE_SIZE;
137 nStackReserve = pinhHeader->OptionalHeader.SizeOfStackReserve;
138 nStackCommit = pinhHeader->OptionalHeader.SizeOfStackCommit;
141 /* FIXME: this should be defined in winbase.h */
142 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
143 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
147 if(dwStackSize == 0);
148 /* dwStackSize specifies the size to reserve */
149 else if(dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION)
150 nStackReserve = dwStackSize;
151 /* dwStackSize specifies the size to commit */
153 nStackCommit = dwStackSize;
155 /* fix the stack reserve size */
156 if(nStackCommit > nStackReserve)
157 nStackReserve = ROUNDUP(nStackCommit, 0x100000);
159 /* initialize the attributes for the thread object */
160 InitializeObjectAttributes
169 if(lpThreadAttributes)
171 /* make the handle inheritable */
172 if(lpThreadAttributes->bInheritHandle)
173 oaThreadAttribs.Attributes |= OBJ_INHERIT;
175 /* user-defined security descriptor */
176 oaThreadAttribs.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
181 "RtlRosCreateUserThreadVa\n"
183 " ProcessHandle %p,\n"
184 " ObjectAttributes %p,\n"
185 " CreateSuspended %d,\n"
186 " StackZeroBits %d,\n"
187 " StackReserve %lu,\n"
188 " StackCommit %lu,\n"
189 " StartAddress %p,\n"
190 " ThreadHandle %p,\n"
192 " ParameterCount %u,\n"
193 " Parameters[0] %p,\n"
194 " Parameters[1] %p\n"
198 dwCreationFlags & CREATE_SUSPENDED,
210 /* create the thread */
211 nErrCode = RtlRosCreateUserThreadVa
215 dwCreationFlags & CREATE_SUSPENDED,
219 (PTHREAD_START_ROUTINE)ThreadStartup,
228 if(!NT_SUCCESS(nErrCode))
230 SetLastErrorByStatus(nErrCode);
239 "ClientId.UniqueThread %p\n",
243 cidClientId.UniqueThread
247 if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
258 return(NtCurrentTeb());
269 errCode = NtYieldExecution();
278 GetCurrentThreadId(VOID)
280 return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
288 ExitThread(DWORD uExitCode)
294 * Terminate process if this is the last thread
295 * of the current process
297 Status = NtQueryInformationThread(NtCurrentThread(),
302 if (NT_SUCCESS(Status) && LastThread == TRUE)
304 ExitProcess(uExitCode);
307 /* FIXME: notify csrss of thread termination */
311 Status = NtTerminateThread(NtCurrentThread(),
313 if (!NT_SUCCESS(Status))
315 SetLastErrorByStatus(Status);
317 for(;;); /* GCC complains noreturn function should not return */
325 GetThreadTimes(HANDLE hThread,
326 LPFILETIME lpCreationTime,
327 LPFILETIME lpExitTime,
328 LPFILETIME lpKernelTime,
329 LPFILETIME lpUserTime)
331 KERNEL_USER_TIMES KernelUserTimes;
335 Status = NtQueryInformationThread(hThread,
338 sizeof(KERNEL_USER_TIMES),
340 if (!NT_SUCCESS(Status))
342 SetLastErrorByStatus(Status);
346 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
347 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
348 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
349 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
359 GetThreadContext(HANDLE hThread,
364 Status = NtGetContextThread(hThread,
366 if (!NT_SUCCESS(Status))
368 SetLastErrorByStatus(Status);
380 SetThreadContext(HANDLE hThread,
381 CONST CONTEXT *lpContext)
385 Status = NtSetContextThread(hThread,
387 if (!NT_SUCCESS(Status))
389 SetLastErrorByStatus(Status);
401 GetExitCodeThread(HANDLE hThread,
404 THREAD_BASIC_INFORMATION ThreadBasic;
408 Status = NtQueryInformationThread(hThread,
409 ThreadBasicInformation,
411 sizeof(THREAD_BASIC_INFORMATION),
413 if (!NT_SUCCESS(Status))
415 SetLastErrorByStatus(Status);
419 memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
429 ResumeThread(HANDLE hThread)
431 ULONG PreviousResumeCount;
434 Status = NtResumeThread(hThread,
435 &PreviousResumeCount);
436 if (!NT_SUCCESS(Status))
438 SetLastErrorByStatus(Status);
442 return(PreviousResumeCount);
450 TerminateThread(HANDLE hThread,
457 SetLastError(ERROR_INVALID_HANDLE);
461 Status = NtTerminateThread(hThread,
463 if (!NT_SUCCESS(Status))
465 SetLastErrorByStatus(Status);
477 SuspendThread(HANDLE hThread)
479 ULONG PreviousSuspendCount;
482 Status = NtSuspendThread(hThread,
483 &PreviousSuspendCount);
484 if (!NT_SUCCESS(Status))
486 SetLastErrorByStatus(Status);
490 return(PreviousSuspendCount);
498 SetThreadAffinityMask(HANDLE hThread,
499 DWORD dwThreadAffinityMask)
501 THREAD_BASIC_INFORMATION ThreadBasic;
502 KAFFINITY AffinityMask;
506 AffinityMask = (KAFFINITY)dwThreadAffinityMask;
508 Status = NtQueryInformationThread(hThread,
509 ThreadBasicInformation,
511 sizeof(THREAD_BASIC_INFORMATION),
513 if (!NT_SUCCESS(Status))
515 SetLastErrorByStatus(Status);
519 Status = NtSetInformationThread(hThread,
523 if (!NT_SUCCESS(Status))
524 SetLastErrorByStatus(Status);
526 return(ThreadBasic.AffinityMask);
534 SetThreadPriority(HANDLE hThread,
537 ULONG Prio = nPriority;
540 Status = NtSetInformationThread(hThread,
545 if (!NT_SUCCESS(Status))
547 SetLastErrorByStatus(Status);
559 GetThreadPriority(HANDLE hThread)
561 THREAD_BASIC_INFORMATION ThreadBasic;
565 Status = NtQueryInformationThread(hThread,
566 ThreadBasicInformation,
568 sizeof(THREAD_BASIC_INFORMATION),
570 if (!NT_SUCCESS(Status))
572 SetLastErrorByStatus(Status);
573 return(THREAD_PRIORITY_ERROR_RETURN);
576 return(ThreadBasic.BasePriority);
584 GetThreadPriorityBoost(IN HANDLE hThread,
585 OUT PBOOL pDisablePriorityBoost)
591 Status = NtQueryInformationThread(hThread,
596 if (!NT_SUCCESS(Status))
598 SetLastErrorByStatus(Status);
602 *pDisablePriorityBoost = !((WINBOOL)PriorityBoost);
612 SetThreadPriorityBoost(IN HANDLE hThread,
613 IN WINBOOL bDisablePriorityBoost)
618 PriorityBoost = (ULONG)!bDisablePriorityBoost;
620 Status = NtSetInformationThread(hThread,
624 if (!NT_SUCCESS(Status))
626 SetLastErrorByStatus(Status);
638 GetThreadSelectorEntry(IN HANDLE hThread,
640 OUT LPLDT_ENTRY lpSelectorEntry)
642 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
651 SetThreadIdealProcessor(HANDLE hThread,
652 DWORD dwIdealProcessor)
654 ULONG IdealProcessor;
657 IdealProcessor = (ULONG)dwIdealProcessor;
659 Status = NtSetInformationThread(hThread,
660 ThreadIdealProcessor,
663 if (!NT_SUCCESS(Status))
665 SetLastErrorByStatus(Status);