1 /* $Id: thread.c,v 1.37 2003/04/26 23:13:28 hyperion 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
13 /* INCLUDES ******************************************************************/
18 #include <kernel32/kernel32.h>
20 //static VOID ThreadAttachDlls (VOID);
22 /* FUNCTIONS *****************************************************************/
24 /* FIXME: please put this in some header */
25 extern NTSTATUS CDECL RtlCreateUserThreadVa
28 POBJECT_ATTRIBUTES ObjectAttributes
,
29 BOOLEAN CreateSuspended
,
33 PTHREAD_START_ROUTINE StartAddress
,
40 static EXCEPTION_DISPOSITION __cdecl
41 _except_handler(EXCEPTION_RECORD
*ExceptionRecord
,
42 void * EstablisherFrame
,
43 CONTEXT
*ContextRecord
,
44 void * DispatcherContext
)
48 /* We should not get to here */
49 return(ExceptionContinueSearch
);
54 ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress
,
59 __try1(_except_handler
)
61 /* FIXME: notify csrss of thread creation ?? */
62 uExitCode
= (lpStartAddress
)(lpParameter
);
68 ExitThread(uExitCode
);
72 HANDLE STDCALL CreateThread
74 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
76 LPTHREAD_START_ROUTINE lpStartAddress
,
78 DWORD dwCreationFlags
,
82 return CreateRemoteThread
95 HANDLE STDCALL CreateRemoteThread
98 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
100 LPTHREAD_START_ROUTINE lpStartAddress
,
102 DWORD dwCreationFlags
,
106 PSECURITY_DESCRIPTOR pSD
= NULL
;
108 CLIENT_ID cidClientId
;
110 ULONG_PTR nStackReserve
;
111 ULONG_PTR nStackCommit
;
112 OBJECT_ATTRIBUTES oaThreadAttribs
;
113 PIMAGE_NT_HEADERS pinhHeader
=
114 RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
116 /* FIXME: do more checks - e.g. the image may not have an optional header */
117 if(pinhHeader
== NULL
)
119 nStackReserve
= 0x100000;
120 nStackCommit
= PAGE_SIZE
;
124 nStackReserve
= pinhHeader
->OptionalHeader
.SizeOfStackReserve
;
125 nStackCommit
= pinhHeader
->OptionalHeader
.SizeOfStackCommit
;
128 /* FIXME: this should be defined in winbase.h */
129 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
130 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
134 if(dwStackSize
== 0);
135 /* dwStackSize specifies the size to reserve */
136 else if(dwCreationFlags
& STACK_SIZE_PARAM_IS_A_RESERVATION
)
137 nStackReserve
= dwStackSize
;
138 /* dwStackSize specifies the size to commit */
140 nStackCommit
= dwStackSize
;
142 /* fix the stack reserve size */
143 if(nStackCommit
> nStackReserve
)
144 nStackReserve
= ROUNDUP(nStackCommit
, 0x100000);
146 /* initialize the attributes for the thread object */
147 InitializeObjectAttributes
156 if(lpThreadAttributes
)
158 /* make the handle inheritable */
159 if(lpThreadAttributes
->bInheritHandle
)
160 oaThreadAttribs
.Attributes
|= OBJ_INHERIT
;
162 /* user-defined security descriptor */
163 oaThreadAttribs
.SecurityDescriptor
= lpThreadAttributes
->lpSecurityDescriptor
;
166 /* create the thread */
167 nErrCode
= RtlCreateUserThreadVa
171 dwCreationFlags
& CREATE_SUSPENDED
,
175 (PTHREAD_START_ROUTINE
)ThreadStartup
,
184 if(!NT_SUCCESS(nErrCode
))
186 SetLastErrorByStatus(nErrCode
);
191 if(lpThreadId
) *lpThreadId
= (DWORD
)cidClientId
.UniqueThread
;
198 return(NtCurrentTeb());
206 errCode
= NtYieldExecution();
212 GetCurrentThreadId(VOID
)
214 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
219 ExitThread(DWORD uExitCode
)
225 * Terminate process if this is the last thread
226 * of the current process
228 Status
= NtQueryInformationThread(NtCurrentThread(),
233 if (NT_SUCCESS(Status
) && LastThread
== TRUE
)
235 ExitProcess(uExitCode
);
238 /* FIXME: notify csrss of thread termination */
242 Status
= NtTerminateThread(NtCurrentThread(),
244 if (!NT_SUCCESS(Status
))
246 SetLastErrorByStatus(Status
);
252 GetThreadTimes(HANDLE hThread
,
253 LPFILETIME lpCreationTime
,
254 LPFILETIME lpExitTime
,
255 LPFILETIME lpKernelTime
,
256 LPFILETIME lpUserTime
)
258 KERNEL_USER_TIMES KernelUserTimes
;
262 Status
= NtQueryInformationThread(hThread
,
265 sizeof(KERNEL_USER_TIMES
),
267 if (!NT_SUCCESS(Status
))
269 SetLastErrorByStatus(Status
);
273 memcpy(lpCreationTime
, &KernelUserTimes
.CreateTime
, sizeof(FILETIME
));
274 memcpy(lpExitTime
, &KernelUserTimes
.ExitTime
, sizeof(FILETIME
));
275 memcpy(lpKernelTime
, &KernelUserTimes
.KernelTime
, sizeof(FILETIME
));
276 memcpy(lpUserTime
, &KernelUserTimes
.UserTime
, sizeof(FILETIME
));
283 GetThreadContext(HANDLE hThread
,
288 Status
= NtGetContextThread(hThread
,
290 if (!NT_SUCCESS(Status
))
292 SetLastErrorByStatus(Status
);
301 SetThreadContext(HANDLE hThread
,
302 CONST CONTEXT
*lpContext
)
306 Status
= NtSetContextThread(hThread
,
308 if (!NT_SUCCESS(Status
))
310 SetLastErrorByStatus(Status
);
319 GetExitCodeThread(HANDLE hThread
,
322 THREAD_BASIC_INFORMATION ThreadBasic
;
326 Status
= NtQueryInformationThread(hThread
,
327 ThreadBasicInformation
,
329 sizeof(THREAD_BASIC_INFORMATION
),
331 if (!NT_SUCCESS(Status
))
333 SetLastErrorByStatus(Status
);
337 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
344 ResumeThread(HANDLE hThread
)
346 ULONG PreviousResumeCount
;
349 Status
= NtResumeThread(hThread
,
350 &PreviousResumeCount
);
351 if (!NT_SUCCESS(Status
))
353 SetLastErrorByStatus(Status
);
357 return(PreviousResumeCount
);
362 TerminateThread(HANDLE hThread
,
369 SetLastError(ERROR_INVALID_HANDLE
);
373 Status
= NtTerminateThread(hThread
,
375 if (!NT_SUCCESS(Status
))
377 SetLastErrorByStatus(Status
);
386 SuspendThread(HANDLE hThread
)
388 ULONG PreviousSuspendCount
;
391 Status
= NtSuspendThread(hThread
,
392 &PreviousSuspendCount
);
393 if (!NT_SUCCESS(Status
))
395 SetLastErrorByStatus(Status
);
399 return(PreviousSuspendCount
);
404 SetThreadAffinityMask(HANDLE hThread
,
405 DWORD dwThreadAffinityMask
)
407 THREAD_BASIC_INFORMATION ThreadBasic
;
408 KAFFINITY AffinityMask
;
412 AffinityMask
= (KAFFINITY
)dwThreadAffinityMask
;
414 Status
= NtQueryInformationThread(hThread
,
415 ThreadBasicInformation
,
417 sizeof(THREAD_BASIC_INFORMATION
),
419 if (!NT_SUCCESS(Status
))
421 SetLastErrorByStatus(Status
);
425 Status
= NtSetInformationThread(hThread
,
429 if (!NT_SUCCESS(Status
))
430 SetLastErrorByStatus(Status
);
432 return(ThreadBasic
.AffinityMask
);
437 SetThreadPriority(HANDLE hThread
,
440 THREAD_BASIC_INFORMATION ThreadBasic
;
444 Status
= NtQueryInformationThread(hThread
,
445 ThreadBasicInformation
,
447 sizeof(THREAD_BASIC_INFORMATION
),
449 if (!NT_SUCCESS(Status
))
451 SetLastErrorByStatus(Status
);
455 ThreadBasic
.BasePriority
= nPriority
;
457 Status
= NtSetInformationThread(hThread
,
458 ThreadBasicInformation
,
460 sizeof(THREAD_BASIC_INFORMATION
));
461 if (!NT_SUCCESS(Status
))
463 SetLastErrorByStatus(Status
);
472 GetThreadPriority(HANDLE hThread
)
474 THREAD_BASIC_INFORMATION ThreadBasic
;
478 Status
= NtQueryInformationThread(hThread
,
479 ThreadBasicInformation
,
481 sizeof(THREAD_BASIC_INFORMATION
),
483 if (!NT_SUCCESS(Status
))
485 SetLastErrorByStatus(Status
);
486 return(THREAD_PRIORITY_ERROR_RETURN
);
489 return(ThreadBasic
.BasePriority
);
494 GetThreadPriorityBoost(IN HANDLE hThread
,
495 OUT PBOOL pDisablePriorityBoost
)
501 Status
= NtQueryInformationThread(hThread
,
506 if (!NT_SUCCESS(Status
))
508 SetLastErrorByStatus(Status
);
512 *pDisablePriorityBoost
= !((WINBOOL
)PriorityBoost
);
519 SetThreadPriorityBoost(IN HANDLE hThread
,
520 IN WINBOOL bDisablePriorityBoost
)
525 PriorityBoost
= (ULONG
)!bDisablePriorityBoost
;
527 Status
= NtSetInformationThread(hThread
,
531 if (!NT_SUCCESS(Status
))
533 SetLastErrorByStatus(Status
);
542 GetThreadSelectorEntry(IN HANDLE hThread
,
544 OUT LPLDT_ENTRY lpSelectorEntry
)
546 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
552 SetThreadIdealProcessor(HANDLE hThread
,
553 DWORD dwIdealProcessor
)
555 ULONG IdealProcessor
;
558 IdealProcessor
= (ULONG
)dwIdealProcessor
;
560 Status
= NtSetInformationThread(hThread
,
561 ThreadIdealProcessor
,
564 if (!NT_SUCCESS(Status
))
566 SetLastErrorByStatus(Status
);