1 /* $Id: thread.c,v 1.42 2003/07/10 18:50:51 chorns 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 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 ThreadStartup
40 LPTHREAD_START_ROUTINE lpStartAddress
,
44 volatile UINT uExitCode
= 0;
46 __try1(_except_handler
)
48 /* FIXME: notify csrss of thread creation ?? */
49 uExitCode
= (lpStartAddress
)(lpParameter
);
55 ExitThread(uExitCode
);
62 HANDLE STDCALL CreateThread
64 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
66 LPTHREAD_START_ROUTINE lpStartAddress
,
68 DWORD dwCreationFlags
,
72 return CreateRemoteThread
88 HANDLE STDCALL CreateRemoteThread
91 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
93 LPTHREAD_START_ROUTINE lpStartAddress
,
95 DWORD dwCreationFlags
,
99 PSECURITY_DESCRIPTOR pSD
= NULL
;
101 CLIENT_ID cidClientId
;
103 ULONG_PTR nStackReserve
;
104 ULONG_PTR nStackCommit
;
105 OBJECT_ATTRIBUTES oaThreadAttribs
;
106 PIMAGE_NT_HEADERS pinhHeader
=
107 RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
112 "lpThreadAttributes %08X\n"
114 "lpStartAddress %08X\n"
116 "dwCreationFlags %08X\n"
127 /* FIXME: do more checks - e.g. the image may not have an optional header */
128 if(pinhHeader
== NULL
)
130 nStackReserve
= 0x100000;
131 nStackCommit
= PAGE_SIZE
;
135 nStackReserve
= pinhHeader
->OptionalHeader
.SizeOfStackReserve
;
136 nStackCommit
= pinhHeader
->OptionalHeader
.SizeOfStackCommit
;
139 /* FIXME: this should be defined in winbase.h */
140 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
141 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
145 if(dwStackSize
== 0);
146 /* dwStackSize specifies the size to reserve */
147 else if(dwCreationFlags
& STACK_SIZE_PARAM_IS_A_RESERVATION
)
148 nStackReserve
= dwStackSize
;
149 /* dwStackSize specifies the size to commit */
151 nStackCommit
= dwStackSize
;
153 /* fix the stack reserve size */
154 if(nStackCommit
> nStackReserve
)
155 nStackReserve
= ROUNDUP(nStackCommit
, 0x100000);
157 /* initialize the attributes for the thread object */
158 InitializeObjectAttributes
167 if(lpThreadAttributes
)
169 /* make the handle inheritable */
170 if(lpThreadAttributes
->bInheritHandle
)
171 oaThreadAttribs
.Attributes
|= OBJ_INHERIT
;
173 /* user-defined security descriptor */
174 oaThreadAttribs
.SecurityDescriptor
= lpThreadAttributes
->lpSecurityDescriptor
;
179 "RtlRosCreateUserThreadVa\n"
181 " ProcessHandle %p,\n"
182 " ObjectAttributes %p,\n"
183 " CreateSuspended %d,\n"
184 " StackZeroBits %d,\n"
185 " StackReserve %lu,\n"
186 " StackCommit %lu,\n"
187 " StartAddress %p,\n"
188 " ThreadHandle %p,\n"
190 " ParameterCount %u,\n"
191 " Parameters[0] %p,\n"
192 " Parameters[1] %p\n"
196 dwCreationFlags
& CREATE_SUSPENDED
,
208 /* create the thread */
209 nErrCode
= RtlRosCreateUserThreadVa
213 dwCreationFlags
& CREATE_SUSPENDED
,
217 (PTHREAD_START_ROUTINE
)ThreadStartup
,
226 if(!NT_SUCCESS(nErrCode
))
228 SetLastErrorByStatus(nErrCode
);
237 "ClientId.UniqueThread %p\n",
241 cidClientId
.UniqueThread
245 if(lpThreadId
) *lpThreadId
= (DWORD
)cidClientId
.UniqueThread
;
256 return(NtCurrentTeb());
267 errCode
= NtYieldExecution();
276 GetCurrentThreadId(VOID
)
278 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
286 ExitThread(DWORD uExitCode
)
292 * Terminate process if this is the last thread
293 * of the current process
295 Status
= NtQueryInformationThread(NtCurrentThread(),
300 if (NT_SUCCESS(Status
) && LastThread
== TRUE
)
302 ExitProcess(uExitCode
);
305 /* FIXME: notify csrss of thread termination */
309 Status
= NtTerminateThread(NtCurrentThread(),
311 if (!NT_SUCCESS(Status
))
313 SetLastErrorByStatus(Status
);
322 GetThreadTimes(HANDLE hThread
,
323 LPFILETIME lpCreationTime
,
324 LPFILETIME lpExitTime
,
325 LPFILETIME lpKernelTime
,
326 LPFILETIME lpUserTime
)
328 KERNEL_USER_TIMES KernelUserTimes
;
332 Status
= NtQueryInformationThread(hThread
,
335 sizeof(KERNEL_USER_TIMES
),
337 if (!NT_SUCCESS(Status
))
339 SetLastErrorByStatus(Status
);
343 memcpy(lpCreationTime
, &KernelUserTimes
.CreateTime
, sizeof(FILETIME
));
344 memcpy(lpExitTime
, &KernelUserTimes
.ExitTime
, sizeof(FILETIME
));
345 memcpy(lpKernelTime
, &KernelUserTimes
.KernelTime
, sizeof(FILETIME
));
346 memcpy(lpUserTime
, &KernelUserTimes
.UserTime
, sizeof(FILETIME
));
356 GetThreadContext(HANDLE hThread
,
361 Status
= NtGetContextThread(hThread
,
363 if (!NT_SUCCESS(Status
))
365 SetLastErrorByStatus(Status
);
377 SetThreadContext(HANDLE hThread
,
378 CONST CONTEXT
*lpContext
)
382 Status
= NtSetContextThread(hThread
,
384 if (!NT_SUCCESS(Status
))
386 SetLastErrorByStatus(Status
);
398 GetExitCodeThread(HANDLE hThread
,
401 THREAD_BASIC_INFORMATION ThreadBasic
;
405 Status
= NtQueryInformationThread(hThread
,
406 ThreadBasicInformation
,
408 sizeof(THREAD_BASIC_INFORMATION
),
410 if (!NT_SUCCESS(Status
))
412 SetLastErrorByStatus(Status
);
416 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
426 ResumeThread(HANDLE hThread
)
428 ULONG PreviousResumeCount
;
431 Status
= NtResumeThread(hThread
,
432 &PreviousResumeCount
);
433 if (!NT_SUCCESS(Status
))
435 SetLastErrorByStatus(Status
);
439 return(PreviousResumeCount
);
447 TerminateThread(HANDLE hThread
,
454 SetLastError(ERROR_INVALID_HANDLE
);
458 Status
= NtTerminateThread(hThread
,
460 if (!NT_SUCCESS(Status
))
462 SetLastErrorByStatus(Status
);
474 SuspendThread(HANDLE hThread
)
476 ULONG PreviousSuspendCount
;
479 Status
= NtSuspendThread(hThread
,
480 &PreviousSuspendCount
);
481 if (!NT_SUCCESS(Status
))
483 SetLastErrorByStatus(Status
);
487 return(PreviousSuspendCount
);
495 SetThreadAffinityMask(HANDLE hThread
,
496 DWORD dwThreadAffinityMask
)
498 THREAD_BASIC_INFORMATION ThreadBasic
;
499 KAFFINITY AffinityMask
;
503 AffinityMask
= (KAFFINITY
)dwThreadAffinityMask
;
505 Status
= NtQueryInformationThread(hThread
,
506 ThreadBasicInformation
,
508 sizeof(THREAD_BASIC_INFORMATION
),
510 if (!NT_SUCCESS(Status
))
512 SetLastErrorByStatus(Status
);
516 Status
= NtSetInformationThread(hThread
,
520 if (!NT_SUCCESS(Status
))
521 SetLastErrorByStatus(Status
);
523 return(ThreadBasic
.AffinityMask
);
531 SetThreadPriority(HANDLE hThread
,
534 ULONG Prio
= nPriority
;
537 Status
= NtSetInformationThread(hThread
,
542 if (!NT_SUCCESS(Status
))
544 SetLastErrorByStatus(Status
);
556 GetThreadPriority(HANDLE hThread
)
558 THREAD_BASIC_INFORMATION ThreadBasic
;
562 Status
= NtQueryInformationThread(hThread
,
563 ThreadBasicInformation
,
565 sizeof(THREAD_BASIC_INFORMATION
),
567 if (!NT_SUCCESS(Status
))
569 SetLastErrorByStatus(Status
);
570 return(THREAD_PRIORITY_ERROR_RETURN
);
573 return(ThreadBasic
.BasePriority
);
581 GetThreadPriorityBoost(IN HANDLE hThread
,
582 OUT PBOOL pDisablePriorityBoost
)
588 Status
= NtQueryInformationThread(hThread
,
593 if (!NT_SUCCESS(Status
))
595 SetLastErrorByStatus(Status
);
599 *pDisablePriorityBoost
= !((WINBOOL
)PriorityBoost
);
609 SetThreadPriorityBoost(IN HANDLE hThread
,
610 IN WINBOOL bDisablePriorityBoost
)
615 PriorityBoost
= (ULONG
)!bDisablePriorityBoost
;
617 Status
= NtSetInformationThread(hThread
,
621 if (!NT_SUCCESS(Status
))
623 SetLastErrorByStatus(Status
);
635 GetThreadSelectorEntry(IN HANDLE hThread
,
637 OUT LPLDT_ENTRY lpSelectorEntry
)
639 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
648 SetThreadIdealProcessor(HANDLE hThread
,
649 DWORD dwIdealProcessor
)
651 ULONG IdealProcessor
;
654 IdealProcessor
= (ULONG
)dwIdealProcessor
;
656 Status
= NtSetInformationThread(hThread
,
657 ThreadIdealProcessor
,
660 if (!NT_SUCCESS(Status
))
662 SetLastErrorByStatus(Status
);