1 /* $Id: thread.c,v 1.49 2004/01/23 21:16:04 ekohl Exp $
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
14 /* INCLUDES ******************************************************************/
19 #include "../include/debug.h"
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
);
287 ExitThread(DWORD uExitCode
)
293 * Terminate process if this is the last thread
294 * of the current process
296 Status
= NtQueryInformationThread(NtCurrentThread(),
301 if (NT_SUCCESS(Status
) && LastThread
== TRUE
)
303 ExitProcess(uExitCode
);
306 /* FIXME: notify csrss of thread termination */
310 RtlRosExitUserThread(uExitCode
);
318 GetThreadTimes(HANDLE hThread
,
319 LPFILETIME lpCreationTime
,
320 LPFILETIME lpExitTime
,
321 LPFILETIME lpKernelTime
,
322 LPFILETIME lpUserTime
)
324 KERNEL_USER_TIMES KernelUserTimes
;
328 Status
= NtQueryInformationThread(hThread
,
331 sizeof(KERNEL_USER_TIMES
),
333 if (!NT_SUCCESS(Status
))
335 SetLastErrorByStatus(Status
);
339 memcpy(lpCreationTime
, &KernelUserTimes
.CreateTime
, sizeof(FILETIME
));
340 memcpy(lpExitTime
, &KernelUserTimes
.ExitTime
, sizeof(FILETIME
));
341 memcpy(lpKernelTime
, &KernelUserTimes
.KernelTime
, sizeof(FILETIME
));
342 memcpy(lpUserTime
, &KernelUserTimes
.UserTime
, sizeof(FILETIME
));
352 GetThreadContext(HANDLE hThread
,
357 Status
= NtGetContextThread(hThread
,
359 if (!NT_SUCCESS(Status
))
361 SetLastErrorByStatus(Status
);
373 SetThreadContext(HANDLE hThread
,
374 CONST CONTEXT
*lpContext
)
378 Status
= NtSetContextThread(hThread
,
380 if (!NT_SUCCESS(Status
))
382 SetLastErrorByStatus(Status
);
394 GetExitCodeThread(HANDLE hThread
,
397 THREAD_BASIC_INFORMATION ThreadBasic
;
401 Status
= NtQueryInformationThread(hThread
,
402 ThreadBasicInformation
,
404 sizeof(THREAD_BASIC_INFORMATION
),
406 if (!NT_SUCCESS(Status
))
408 SetLastErrorByStatus(Status
);
412 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
422 ResumeThread(HANDLE hThread
)
424 ULONG PreviousResumeCount
;
427 Status
= NtResumeThread(hThread
,
428 &PreviousResumeCount
);
429 if (!NT_SUCCESS(Status
))
431 SetLastErrorByStatus(Status
);
435 return(PreviousResumeCount
);
443 TerminateThread(HANDLE hThread
,
450 SetLastError(ERROR_INVALID_HANDLE
);
454 Status
= NtTerminateThread(hThread
,
456 if (!NT_SUCCESS(Status
))
458 SetLastErrorByStatus(Status
);
470 SuspendThread(HANDLE hThread
)
472 ULONG PreviousSuspendCount
;
475 Status
= NtSuspendThread(hThread
,
476 &PreviousSuspendCount
);
477 if (!NT_SUCCESS(Status
))
479 SetLastErrorByStatus(Status
);
483 return(PreviousSuspendCount
);
491 SetThreadAffinityMask(HANDLE hThread
,
492 DWORD dwThreadAffinityMask
)
494 THREAD_BASIC_INFORMATION ThreadBasic
;
495 KAFFINITY AffinityMask
;
499 AffinityMask
= (KAFFINITY
)dwThreadAffinityMask
;
501 Status
= NtQueryInformationThread(hThread
,
502 ThreadBasicInformation
,
504 sizeof(THREAD_BASIC_INFORMATION
),
506 if (!NT_SUCCESS(Status
))
508 SetLastErrorByStatus(Status
);
512 Status
= NtSetInformationThread(hThread
,
516 if (!NT_SUCCESS(Status
))
517 SetLastErrorByStatus(Status
);
519 return(ThreadBasic
.AffinityMask
);
527 SetThreadPriority(HANDLE hThread
,
530 ULONG Prio
= nPriority
;
533 Status
= NtSetInformationThread(hThread
,
538 if (!NT_SUCCESS(Status
))
540 SetLastErrorByStatus(Status
);
552 GetThreadPriority(HANDLE hThread
)
554 THREAD_BASIC_INFORMATION ThreadBasic
;
558 Status
= NtQueryInformationThread(hThread
,
559 ThreadBasicInformation
,
561 sizeof(THREAD_BASIC_INFORMATION
),
563 if (!NT_SUCCESS(Status
))
565 SetLastErrorByStatus(Status
);
566 return(THREAD_PRIORITY_ERROR_RETURN
);
569 return(ThreadBasic
.BasePriority
);
577 GetThreadPriorityBoost(IN HANDLE hThread
,
578 OUT PBOOL pDisablePriorityBoost
)
584 Status
= NtQueryInformationThread(hThread
,
589 if (!NT_SUCCESS(Status
))
591 SetLastErrorByStatus(Status
);
595 *pDisablePriorityBoost
= !((BOOL
)PriorityBoost
);
605 SetThreadPriorityBoost(IN HANDLE hThread
,
606 IN BOOL bDisablePriorityBoost
)
611 PriorityBoost
= (ULONG
)!bDisablePriorityBoost
;
613 Status
= NtSetInformationThread(hThread
,
617 if (!NT_SUCCESS(Status
))
619 SetLastErrorByStatus(Status
);
631 GetThreadSelectorEntry(IN HANDLE hThread
,
633 OUT LPLDT_ENTRY lpSelectorEntry
)
635 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
644 SetThreadIdealProcessor(HANDLE hThread
,
645 DWORD dwIdealProcessor
)
647 ULONG IdealProcessor
;
650 IdealProcessor
= (ULONG
)dwIdealProcessor
;
652 Status
= NtSetInformationThread(hThread
,
653 ThreadIdealProcessor
,
656 if (!NT_SUCCESS(Status
))
658 SetLastErrorByStatus(Status
);