2005-01-06 13:58:04 +00:00
|
|
|
/* $Id$
|
2000-05-30 23:41:06 +00:00
|
|
|
*
|
1999-05-29 00:15:17 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* FILE: lib/kernel32/thread/tls.c
|
|
|
|
* PURPOSE: Thread functions
|
|
|
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
1999-10-07 23:46:27 +00:00
|
|
|
* Tls functions are modified from WINE
|
1999-05-29 00:15:17 +00:00
|
|
|
* UPDATE HISTORY:
|
|
|
|
* Created 01/11/98
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
2000-11-19 16:01:29 +00:00
|
|
|
#define NDEBUG
|
2007-09-02 19:42:22 +00:00
|
|
|
#include <debug.h>
|
2000-11-19 16:01:29 +00:00
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-09-06 14:12:47 +00:00
|
|
|
DWORD
|
|
|
|
WINAPI
|
2001-03-13 16:25:55 +00:00
|
|
|
TlsAlloc(VOID)
|
1999-05-29 00:15:17 +00:00
|
|
|
{
|
2008-09-06 14:12:47 +00:00
|
|
|
ULONG Index;
|
|
|
|
|
|
|
|
RtlAcquirePebLock();
|
|
|
|
|
|
|
|
/* Try to get regular TEB slot. */
|
|
|
|
Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsBitmap, 1, 0);
|
2008-12-03 17:33:13 +00:00
|
|
|
if (Index == ~0U)
|
2008-09-06 14:12:47 +00:00
|
|
|
{
|
|
|
|
/* If it fails, try to find expansion TEB slot. */
|
|
|
|
Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsExpansionBitmap, 1, 0);
|
2008-12-03 17:33:13 +00:00
|
|
|
if (Index != ~0U)
|
2008-09-06 14:12:47 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
|
|
|
/* Clear the value. */
|
|
|
|
NtCurrentTeb()->TlsSlots[Index] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlReleasePebLock();
|
|
|
|
|
|
|
|
return Index;
|
1999-05-29 00:15:17 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-09-06 14:12:47 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2005-12-08 00:38:57 +00:00
|
|
|
TlsFree(DWORD Index)
|
1999-05-29 00:15:17 +00:00
|
|
|
{
|
2008-09-06 14:12:47 +00:00
|
|
|
BOOL BitSet;
|
2010-01-09 20:51:33 +00:00
|
|
|
|
2008-09-06 14:12:47 +00:00
|
|
|
if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlAcquirePebLock();
|
|
|
|
|
|
|
|
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 BitSet;
|
1999-05-29 00:15:17 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-09-06 14:12:47 +00:00
|
|
|
LPVOID
|
|
|
|
WINAPI
|
2005-12-08 00:38:57 +00:00
|
|
|
TlsGetValue(DWORD Index)
|
1999-05-29 00:15:17 +00:00
|
|
|
{
|
2008-09-06 14:12:47 +00:00
|
|
|
if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE)
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
}
|
1999-05-29 00:15:17 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-09-06 14:12:47 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
TlsSetValue(DWORD Index,
|
|
|
|
LPVOID Value)
|
1999-05-29 00:15:17 +00:00
|
|
|
{
|
2008-09-06 14:12:47 +00:00
|
|
|
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;
|
1999-05-29 00:15:17 +00:00
|
|
|
}
|