X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=dll%2Fwin32%2Fkernel32%2Fclient%2Fthread.c;fp=dll%2Fwin32%2Fkernel32%2Fthread%2Fthread.c;h=13975dfaad147680e87643d5c72517da1c9291b5;hp=055342a0d39a9aa8fb8eb5c3515cead7e8b0f769;hb=b1d8a4df819c95bcb81cd8d6e8d9a397125147a9;hpb=8b36c2fed55e2160b52793adcf111914ded5d10a diff --git a/dll/win32/kernel32/thread/thread.c b/dll/win32/kernel32/client/thread.c similarity index 75% rename from dll/win32/kernel32/thread/thread.c rename to dll/win32/kernel32/client/thread.c index 055342a0d39..13975dfaad1 100644 --- a/dll/win32/kernel32/thread/thread.c +++ b/dll/win32/kernel32/client/thread.c @@ -52,22 +52,34 @@ WINAPI BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter) { - volatile UINT uExitCode = 0; - /* Attempt to call the Thread Start Address */ _SEH2_TRY { + /* Legacy check which is still used today for Win32 threads */ + if (NtCurrentTeb()->NtTib.Version == (30 << 8)) // OS/2 V3.0 ("Cruiser") + { + /* This registers the termination port with CSRSS */ + if (!BaseRunningInServerProcess) CsrNewThread(); + } + /* Get the exit code from the Thread Start */ - uExitCode = (lpStartAddress)((PVOID)lpParameter); + ExitThread((lpStartAddress)((PVOID)lpParameter)); } _SEH2_EXCEPT(BaseThreadExceptionFilter(_SEH2_GetExceptionInformation())) { /* Get the Exit code from the SEH Handler */ - uExitCode = _SEH2_GetExceptionCode(); - } _SEH2_END; - - /* Exit the Thread */ - ExitThread(uExitCode); + if (!BaseRunningInServerProcess) + { + /* Kill the whole process, usually */ + ExitProcess(_SEH2_GetExceptionCode()); + } + else + { + /* If running inside CSRSS, kill just this thread */ + ExitThread(_SEH2_GetExceptionCode()); + } + } + _SEH2_END; } /* @@ -132,7 +144,7 @@ CreateRemoteThread(HANDLE hProcess, &InitialTeb); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -160,7 +172,7 @@ CreateRemoteThread(HANDLE hProcess, if(!NT_SUCCESS(Status)) { BasepFreeStack(hProcess, &InitialTeb); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -230,7 +242,7 @@ CreateRemoteThread(HANDLE hProcess, { ASSERT(FALSE); } - + /* Success */ if(lpThreadId) *lpThreadId = HandleToUlong(ClientId.UniqueThread); @@ -310,7 +322,7 @@ OpenThread(DWORD dwDesiredAccess, &ClientId); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -368,7 +380,7 @@ GetThreadTimes(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return(FALSE); } @@ -392,7 +404,7 @@ GetThreadContext(HANDLE hThread, Status = NtGetContextThread(hThread, lpContext); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -412,7 +424,7 @@ SetThreadContext(HANDLE hThread, Status = NtSetContextThread(hThread, (PCONTEXT)lpContext); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -437,7 +449,7 @@ GetExitCodeThread(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return(FALSE); } @@ -458,7 +470,7 @@ ResumeThread(HANDLE hThread) Status = NtResumeThread(hThread, &PreviousResumeCount); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -484,7 +496,7 @@ TerminateThread(HANDLE hThread, Status = NtTerminateThread(hThread, dwExitCode); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -504,7 +516,7 @@ SuspendThread(HANDLE hThread) Status = NtSuspendThread(hThread, &PreviousSuspendCount); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -532,7 +544,7 @@ SetThreadAffinityMask(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -542,7 +554,7 @@ SetThreadAffinityMask(HANDLE hThread, sizeof(KAFFINITY)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); ThreadBasic.AffinityMask = 0; } @@ -578,7 +590,7 @@ SetThreadPriority(HANDLE hThread, if (!NT_SUCCESS(Status)) { /* Failure */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -605,17 +617,19 @@ GetThreadPriority(HANDLE hThread) if (!NT_SUCCESS(Status)) { /* Failure */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return THREAD_PRIORITY_ERROR_RETURN; } - /* Do some conversions for out of boundary values */ - if (ThreadBasic.BasePriority > THREAD_BASE_PRIORITY_MAX) + /* Do some conversions for saturation values */ + if (ThreadBasic.BasePriority == ((HIGH_PRIORITY + 1) / 2)) { + /* Win32 calls this "time critical" */ ThreadBasic.BasePriority = THREAD_PRIORITY_TIME_CRITICAL; } - else if (ThreadBasic.BasePriority < THREAD_BASE_PRIORITY_MIN) + else if (ThreadBasic.BasePriority == -((HIGH_PRIORITY + 1) / 2)) { + /* Win32 calls this "idle" */ ThreadBasic.BasePriority = THREAD_PRIORITY_IDLE; } @@ -641,7 +655,7 @@ GetThreadPriorityBoost(IN HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -668,7 +682,7 @@ SetThreadPriorityBoost(IN HANDLE hThread, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -698,7 +712,7 @@ GetThreadSelectorEntry(IN HANDLE hThread, if (!NT_SUCCESS(Status)) { /* Fail */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -727,7 +741,7 @@ SetThreadIdealProcessor(HANDLE hThread, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -750,7 +764,7 @@ GetProcessIdOfThread(HANDLE Thread) NULL); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -773,7 +787,7 @@ GetThreadId(HANDLE Thread) NULL); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -809,13 +823,22 @@ QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData) (PVOID)dwData, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } return 1; } +BOOL +WINAPI +SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes) +{ + STUB; + return FALSE; +} + + /* * @implemented */ @@ -843,53 +866,11 @@ GetThreadIOPendingFlag(HANDLE hThread, return TRUE; } - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } -/* - * @implemented - */ -VOID WINAPI -Sleep(DWORD dwMilliseconds) -{ - SleepEx(dwMilliseconds, FALSE); - return; -} - - -/* - * @implemented - */ -DWORD WINAPI -SleepEx(DWORD dwMilliseconds, - BOOL bAlertable) -{ - LARGE_INTEGER Interval; - NTSTATUS errCode; - - if (dwMilliseconds != INFINITE) - { - /* - * System time units are 100 nanoseconds (a nanosecond is a billionth of - * a second). - */ - Interval.QuadPart = -((LONGLONG)dwMilliseconds * 10000); - } - else - { - /* Approximately 292000 years hence */ - Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL; - } - -dowait: - errCode = NtDelayExecution ((BOOLEAN)bAlertable, &Interval); - if ((bAlertable) && (errCode == STATUS_ALERTED)) goto dowait; - return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; -} - - typedef struct _QUEUE_USER_WORKITEM_CONTEXT { LPTHREAD_START_ROUTINE Function; @@ -957,117 +938,248 @@ QueueUserWorkItem( 0, WorkItemContext); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } return TRUE; } - /* * @implemented */ -BOOL +DWORD WINAPI -RegisterWaitForSingleObject( - PHANDLE phNewWaitObject, - HANDLE hObject, - WAITORTIMERCALLBACK Callback, - PVOID Context, - ULONG dwMilliseconds, - ULONG dwFlags - ) +TlsAlloc(VOID) { - NTSTATUS Status = RtlRegisterWait(phNewWaitObject, - hObject, - Callback, - Context, - dwMilliseconds, - dwFlags); + ULONG Index; + PTEB Teb; + PPEB Peb; + + /* Get the PEB and TEB, lock the PEB */ + Teb = NtCurrentTeb(); + Peb = Teb->ProcessEnvironmentBlock; + RtlAcquirePebLock(); + + /* Try to get regular TEB slot */ + Index = RtlFindClearBitsAndSet(Peb->TlsBitmap, 1, 0); + if (Index != 0xFFFFFFFF) + { + /* Clear the value. */ + Teb->TlsSlots[Index] = 0; + RtlReleasePebLock(); + return Index; + } - if (!NT_SUCCESS(Status)) + /* If it fails, try to find expansion TEB slot. */ + Index = RtlFindClearBitsAndSet(Peb->TlsExpansionBitmap, 1, 0); + if (Index != 0xFFFFFFFF) { - SetLastErrorByStatus(Status); - return FALSE; + /* Is there no expansion slot yet? */ + if (!Teb->TlsExpansionSlots) + { + /* Allocate an array */ + Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * + sizeof(PVOID)); + } + + /* Did we get an array? */ + if (!Teb->TlsExpansionSlots) + { + /* Fail */ + RtlClearBits(Peb->TlsExpansionBitmap, Index, 1); + Index = 0xFFFFFFFF; + BaseSetLastNTError(STATUS_NO_MEMORY); + } + else + { + /* Clear the value. */ + Teb->TlsExpansionSlots[Index] = 0; + Index += TLS_MINIMUM_AVAILABLE; + } + } + else + { + /* Fail */ + BaseSetLastNTError(STATUS_NO_MEMORY); } - return TRUE; -} + /* Release the lock and return */ + RtlReleasePebLock(); + return Index; +} /* * @implemented */ -HANDLE +BOOL WINAPI -RegisterWaitForSingleObjectEx( - HANDLE hObject, - WAITORTIMERCALLBACK Callback, - PVOID Context, - ULONG dwMilliseconds, - ULONG dwFlags - ) +TlsFree(IN DWORD Index) { + BOOL BitSet; + PPEB Peb; + ULONG TlsIndex; + PVOID TlsBitmap; NTSTATUS Status; - HANDLE hNewWaitObject; - Status = RtlRegisterWait(&hNewWaitObject, - hObject, - Callback, - Context, - dwMilliseconds, - dwFlags); + /* Acquire the PEB lock and grab the PEB */ + Peb = NtCurrentPeb(); + RtlAcquirePebLock(); - if (!NT_SUCCESS(Status)) + /* Check if the index is too high */ + if (Index >= TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); - return NULL; + /* Check if it can fit in the expansion slots */ + TlsIndex = Index - TLS_MINIMUM_AVAILABLE; + if (TlsIndex >= TLS_EXPANSION_SLOTS) + { + /* It's invalid */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + else + { + /* Use the expansion bitmap */ + TlsBitmap = Peb->TlsExpansionBitmap; + Index = TlsIndex; + } + } + else + { + /* Use the normal bitmap */ + TlsBitmap = Peb->TlsBitmap; } - return hNewWaitObject; -} + /* Check if the index was set */ + BitSet = RtlAreBitsSet(TlsBitmap, Index, 1); + if (BitSet) + { + /* Tell the kernel to free the TLS cells */ + Status = NtSetInformationThread(NtCurrentThread(), + ThreadZeroTlsCell, + &Index, + sizeof(DWORD)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + /* Clear the bit */ + RtlClearBits(TlsBitmap, Index, 1); + } + else + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + + /* Done! */ + RtlReleasePebLock(); + return TRUE; +} /* * @implemented */ -BOOL +LPVOID WINAPI -UnregisterWait( - HANDLE WaitHandle - ) +TlsGetValue(IN DWORD Index) { - NTSTATUS Status = RtlDeregisterWaitEx(WaitHandle, NULL); + PTEB Teb; - if (!NT_SUCCESS(Status)) + /* Get the TEB and clear the last error */ + Teb = NtCurrentTeb(); + Teb->LastErrorValue = 0; + + /* Check for simple TLS index */ + if (Index < TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); - return FALSE; + /* Return it */ + return Teb->TlsSlots[Index]; } - return TRUE; -} + /* Check for valid index */ + if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return NULL; + } + /* The expansion slots are allocated on demand, so check for it. */ + Teb->LastErrorValue = 0; + if (!Teb->TlsExpansionSlots) return NULL; + + /* Return the value from the expansion slots */ + return Teb->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE]; +} /* * @implemented */ BOOL WINAPI -UnregisterWaitEx( - HANDLE WaitHandle, - HANDLE CompletionEvent - ) +TlsSetValue(IN DWORD Index, + IN LPVOID Value) { - NTSTATUS Status = RtlDeregisterWaitEx(WaitHandle, CompletionEvent); + DWORD TlsIndex; + PTEB Teb = NtCurrentTeb(); - if (!NT_SUCCESS(Status)) + /* Check for simple TLS index */ + if (Index < TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); + /* Return it */ + Teb->TlsSlots[Index] = Value; + return TRUE; + } + + /* Check if this is an expansion slot */ + TlsIndex = Index - TLS_MINIMUM_AVAILABLE; + if (TlsIndex >= TLS_EXPANSION_SLOTS) + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } + /* Do we not have expansion slots? */ + if (!Teb->TlsExpansionSlots) + { + /* Get the PEB lock to see if we still need them */ + RtlAcquirePebLock(); + if (!Teb->TlsExpansionSlots) + { + /* Allocate them */ + Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * + sizeof(PVOID)); + if (!Teb->TlsExpansionSlots) + { + /* Fail */ + RtlReleasePebLock(); + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + } + + /* Release the lock */ + RtlReleasePebLock(); + } + + /* Write the value */ + Teb->TlsExpansionSlots[TlsIndex] = Value; + + /* Success */ return TRUE; } + /* EOF */