- Allow TLS usage for 1088 TLS slots, fixes part of Bug 191. Patch by Filip Navara (navaraf@reactos.com)

svn path=/trunk/; revision=19959
This commit is contained in:
Alex Ionescu 2005-12-08 00:38:57 +00:00
parent bc31c23df9
commit ba70f8d6f5

View file

@ -17,6 +17,7 @@
#define NDEBUG #define NDEBUG
#include "../include/debug.h" #include "../include/debug.h"
#define TLS_EXPANSION_SLOTS (8 * sizeof(((PPEB)NULL)->TlsExpansionBitmapBits))
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -29,18 +30,49 @@ TlsAlloc(VOID)
ULONG Index; ULONG Index;
RtlAcquirePebLock(); RtlAcquirePebLock();
/* Try to get regular TEB slot. */
Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsBitmap, 1, 0); Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsBitmap, 1, 0);
if (Index == (ULONG)-1) if (Index == ~0)
{ {
SetLastErrorByStatus(STATUS_NO_MEMORY); /* 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 else
{ {
/* Clear the value. */
NtCurrentTeb()->TlsExpansionSlots[Index] = 0;
Index += TLS_MINIMUM_AVAILABLE;
}
}
else
{
SetLastError(ERROR_NO_MORE_ITEMS);
}
}
else
{
/* Clear the value. */
NtCurrentTeb()->TlsSlots[Index] = 0; NtCurrentTeb()->TlsSlots[Index] = 0;
} }
RtlReleasePebLock(); RtlReleasePebLock();
return(Index); return Index;
} }
@ -48,32 +80,47 @@ TlsAlloc(VOID)
* @implemented * @implemented
*/ */
BOOL STDCALL BOOL STDCALL
TlsFree(DWORD dwTlsIndex) TlsFree(DWORD Index)
{ {
if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) BOOL BitSet;
if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
{ {
SetLastErrorByStatus(STATUS_INVALID_PARAMETER); SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
return(FALSE); return FALSE;
} }
RtlAcquirePebLock(); RtlAcquirePebLock();
if (RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, dwTlsIndex, 1))
if (Index >= TLS_MINIMUM_AVAILABLE)
{ {
/* BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsExpansionBitmap,
* clear the tls cells (slots) in all threads Index - TLS_MINIMUM_AVAILABLE, 1);
* of the current process if (BitSet)
*/ RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap,
NtSetInformationThread(NtCurrentThread(), Index - TLS_MINIMUM_AVAILABLE, 1);
ThreadZeroTlsCell,
&dwTlsIndex,
sizeof(DWORD));
RtlClearBits(NtCurrentPeb()->TlsBitmap,
dwTlsIndex,
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(); RtlReleasePebLock();
return(TRUE); return BitSet;
} }
@ -81,22 +128,27 @@ TlsFree(DWORD dwTlsIndex)
* @implemented * @implemented
*/ */
LPVOID STDCALL LPVOID STDCALL
TlsGetValue(DWORD dwTlsIndex) TlsGetValue(DWORD Index)
{ {
LPVOID Value; if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE)
{ {
SetLastErrorByStatus(STATUS_INVALID_PARAMETER); SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
return(NULL); return NULL;
} }
Value = NtCurrentTeb()->TlsSlots[dwTlsIndex];
if (Value == 0)
{
SetLastError(NO_ERROR); SetLastError(NO_ERROR);
if (Index >= TLS_MINIMUM_AVAILABLE)
{
/* 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 * @implemented
*/ */
BOOL STDCALL BOOL STDCALL
TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) TlsSetValue(DWORD Index, LPVOID Value)
{ {
if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
{ {
SetLastErrorByStatus(STATUS_INVALID_PARAMETER); SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
return(FALSE); return FALSE;
} }
NtCurrentTeb()->TlsSlots[dwTlsIndex] = lpTlsValue;
return(TRUE); 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 */ /* EOF */