- Allow TLS usage for 1088 TLS slots, fixes part of Bug 191. Patch by Filip Navara (navaraf@reactos.com) Modified: trunk/reactos/lib/kernel32/thread/tls.c _____
Modified: trunk/reactos/lib/kernel32/thread/tls.c --- trunk/reactos/lib/kernel32/thread/tls.c 2005-12-08 00:14:59 UTC (rev 19958) +++ trunk/reactos/lib/kernel32/thread/tls.c 2005-12-08 00:38:57 UTC (rev 19959) @@ -17,6 +17,7 @@
#define NDEBUG #include "../include/debug.h"
+#define TLS_EXPANSION_SLOTS (8 * sizeof(((PPEB)NULL)->TlsExpansionBitmapBits))
/* FUNCTIONS *****************************************************************/
@@ -29,18 +30,49 @@ 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 @@ * @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 @@ * @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]; } - return Value; + else + { + return NtCurrentTeb()->TlsSlots[Index]; + } }
@@ -104,15 +156,37 @@ * @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 */