From ba70f8d6f5495d329a8930c89752a262a99bd30c Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 8 Dec 2005 00:38:57 +0000 Subject: [PATCH] - Allow TLS usage for 1088 TLS slots, fixes part of Bug 191. Patch by Filip Navara (navaraf@reactos.com) svn path=/trunk/; revision=19959 --- reactos/lib/kernel32/thread/tls.c | 172 +++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 49 deletions(-) diff --git a/reactos/lib/kernel32/thread/tls.c b/reactos/lib/kernel32/thread/tls.c index 767f4734b33..357cae3b021 100644 --- a/reactos/lib/kernel32/thread/tls.c +++ b/reactos/lib/kernel32/thread/tls.c @@ -17,6 +17,7 @@ #define NDEBUG #include "../include/debug.h" +#define TLS_EXPANSION_SLOTS (8 * sizeof(((PPEB)NULL)->TlsExpansionBitmapBits)) /* FUNCTIONS *****************************************************************/ @@ -29,18 +30,49 @@ TlsAlloc(VOID) ULONG Index; RtlAcquirePebLock(); - Index = RtlFindClearBitsAndSet (NtCurrentPeb()->TlsBitmap, 1, 0); - if (Index == (ULONG)-1) - { - SetLastErrorByStatus(STATUS_NO_MEMORY); - } + + /* Try to get regular TEB slot. */ + Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsBitmap, 1, 0); + if (Index == ~0) + { + /* If it fails, try to find expansion TEB slot. */ + Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsExpansionBitmap, 1, 0); + if (Index != ~0) + { + if (NtCurrentTeb()->TlsExpansionSlots == NULL) + { + NtCurrentTeb()->TlsExpansionSlots = HeapAlloc( + GetProcessHeap(), HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * sizeof(PVOID)); + } + + if (NtCurrentTeb()->TlsExpansionSlots == NULL) + { + RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap, Index, 1); + Index = ~0; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + else + { + /* Clear the value. */ + NtCurrentTeb()->TlsExpansionSlots[Index] = 0; + Index += TLS_MINIMUM_AVAILABLE; + } + } + else + { + SetLastError(ERROR_NO_MORE_ITEMS); + } + } else - { - NtCurrentTeb()->TlsSlots[Index] = 0; - } + { + /* Clear the value. */ + NtCurrentTeb()->TlsSlots[Index] = 0; + } + RtlReleasePebLock(); - return(Index); + return Index; } @@ -48,32 +80,47 @@ TlsAlloc(VOID) * @implemented */ BOOL STDCALL -TlsFree(DWORD dwTlsIndex) +TlsFree(DWORD Index) { - if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return(FALSE); - } + BOOL BitSet; + + if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return FALSE; + } RtlAcquirePebLock(); - if (RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, dwTlsIndex, 1)) - { - /* - * clear the tls cells (slots) in all threads - * of the current process - */ - NtSetInformationThread(NtCurrentThread(), - ThreadZeroTlsCell, - &dwTlsIndex, - sizeof(DWORD)); - RtlClearBits(NtCurrentPeb()->TlsBitmap, - dwTlsIndex, - 1); - } + + if (Index >= TLS_MINIMUM_AVAILABLE) + { + BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsExpansionBitmap, + Index - TLS_MINIMUM_AVAILABLE, 1); + if (BitSet) + RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap, + Index - TLS_MINIMUM_AVAILABLE, 1); + } + else + { + BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, Index, 1); + if (BitSet) + RtlClearBits(NtCurrentPeb()->TlsBitmap, Index, 1); + } + + if (BitSet) + { + /* Clear the TLS cells (slots) in all threads of the current process. */ + NtSetInformationThread(NtCurrentThread(), ThreadZeroTlsCell, + &Index, sizeof(DWORD)); + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + } + RtlReleasePebLock(); - return(TRUE); + return BitSet; } @@ -81,22 +128,27 @@ TlsFree(DWORD dwTlsIndex) * @implemented */ LPVOID STDCALL -TlsGetValue(DWORD dwTlsIndex) +TlsGetValue(DWORD Index) { - LPVOID Value; + if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return NULL; + } - if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return(NULL); - } + SetLastError(NO_ERROR); - Value = NtCurrentTeb()->TlsSlots[dwTlsIndex]; - if (Value == 0) + if (Index >= TLS_MINIMUM_AVAILABLE) { - SetLastError(NO_ERROR); + /* The expansion slots are allocated on demand, so check for it. */ + if (NtCurrentTeb()->TlsExpansionSlots == NULL) + return NULL; + return NtCurrentTeb()->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE]; + } + else + { + return NtCurrentTeb()->TlsSlots[Index]; } - return Value; } @@ -104,15 +156,37 @@ TlsGetValue(DWORD dwTlsIndex) * @implemented */ BOOL STDCALL -TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) +TlsSetValue(DWORD Index, LPVOID Value) { - if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return(FALSE); - } - NtCurrentTeb()->TlsSlots[dwTlsIndex] = lpTlsValue; - return(TRUE); + if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return FALSE; + } + + if (Index >= TLS_MINIMUM_AVAILABLE) + { + if (NtCurrentTeb()->TlsExpansionSlots == NULL) + { + NtCurrentTeb()->TlsExpansionSlots = HeapAlloc( + GetProcessHeap(), HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * sizeof(PVOID)); + + if (NtCurrentTeb()->TlsExpansionSlots == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + NtCurrentTeb()->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE] = Value; + } + else + { + NtCurrentTeb()->TlsSlots[Index] = Value; + } + + return TRUE; } /* EOF */ -- 2.17.1