- Allow TLS usage for 1088 TLS slots, fixes part of Bug 191. Patch by
Filip Navara (navaraf(a)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 */