Commit f1020bc6 authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for the TLS expansion slots, adding an extra 1024

entries.
parent 2b3aa7c5
...@@ -2192,11 +2192,32 @@ UINT WINAPI SetErrorMode( UINT mode ) ...@@ -2192,11 +2192,32 @@ UINT WINAPI SetErrorMode( UINT mode )
DWORD WINAPI TlsAlloc( void ) DWORD WINAPI TlsAlloc( void )
{ {
DWORD index; DWORD index;
PEB * const peb = NtCurrentTeb()->Peb;
RtlAcquirePebLock(); RtlAcquirePebLock();
index = RtlFindClearBitsAndSet( NtCurrentTeb()->Peb->TlsBitmap, 1, 0 ); index = RtlFindClearBitsAndSet( peb->TlsBitmap, 1, 0 );
if (index != ~0UL) NtCurrentTeb()->TlsSlots[index] = 0; /* clear the value */ if (index != ~0UL) NtCurrentTeb()->TlsSlots[index] = 0; /* clear the value */
else SetLastError( ERROR_NO_MORE_ITEMS ); else
{
index = RtlFindClearBitsAndSet( peb->TlsExpansionBitmap, 1, 0 );
if (index != ~0UL)
{
if (!NtCurrentTeb()->TlsExpansionSlots &&
!(NtCurrentTeb()->TlsExpansionSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
8 * sizeof(peb->TlsExpansionBitmapBits) * sizeof(void*) )))
{
RtlClearBits( peb->TlsExpansionBitmap, index, 1 );
index = ~0UL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
else
{
NtCurrentTeb()->TlsExpansionSlots[index] = 0; /* clear the value */
index += TLS_MINIMUM_AVAILABLE;
}
}
else SetLastError( ERROR_NO_MORE_ITEMS );
}
RtlReleasePebLock(); RtlReleasePebLock();
return index; return index;
} }
...@@ -2217,12 +2238,17 @@ BOOL WINAPI TlsFree( ...@@ -2217,12 +2238,17 @@ BOOL WINAPI TlsFree(
BOOL ret; BOOL ret;
RtlAcquirePebLock(); RtlAcquirePebLock();
ret = RtlAreBitsSet( NtCurrentTeb()->Peb->TlsBitmap, index, 1 ); if (index >= TLS_MINIMUM_AVAILABLE)
if (ret) {
ret = RtlAreBitsSet( NtCurrentTeb()->Peb->TlsExpansionBitmap, index - TLS_MINIMUM_AVAILABLE, 1 );
if (ret) RtlClearBits( NtCurrentTeb()->Peb->TlsExpansionBitmap, index - TLS_MINIMUM_AVAILABLE, 1 );
}
else
{ {
RtlClearBits( NtCurrentTeb()->Peb->TlsBitmap, index, 1 ); ret = RtlAreBitsSet( NtCurrentTeb()->Peb->TlsBitmap, index, 1 );
NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, &index, sizeof(index) ); if (ret) RtlClearBits( NtCurrentTeb()->Peb->TlsBitmap, index, 1 );
} }
if (ret) NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, &index, sizeof(index) );
else SetLastError( ERROR_INVALID_PARAMETER ); else SetLastError( ERROR_INVALID_PARAMETER );
RtlReleasePebLock(); RtlReleasePebLock();
return TRUE; return TRUE;
...@@ -2239,13 +2265,25 @@ BOOL WINAPI TlsFree( ...@@ -2239,13 +2265,25 @@ BOOL WINAPI TlsFree(
LPVOID WINAPI TlsGetValue( LPVOID WINAPI TlsGetValue(
DWORD index) /* [in] TLS index to retrieve value for */ DWORD index) /* [in] TLS index to retrieve value for */
{ {
if (index >= NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap) LPVOID ret;
if (index < TLS_MINIMUM_AVAILABLE)
{ {
SetLastError( ERROR_INVALID_PARAMETER ); ret = NtCurrentTeb()->TlsSlots[index];
return NULL; }
else
{
index -= TLS_MINIMUM_AVAILABLE;
if (index >= 8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits))
{
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
if (!NtCurrentTeb()->TlsExpansionSlots) ret = NULL;
else ret = NtCurrentTeb()->TlsExpansionSlots[index];
} }
SetLastError( ERROR_SUCCESS ); SetLastError( ERROR_SUCCESS );
return NtCurrentTeb()->TlsSlots[index]; return ret;
} }
...@@ -2260,12 +2298,27 @@ BOOL WINAPI TlsSetValue( ...@@ -2260,12 +2298,27 @@ BOOL WINAPI TlsSetValue(
DWORD index, /* [in] TLS index to set value for */ DWORD index, /* [in] TLS index to set value for */
LPVOID value) /* [in] Value to be stored */ LPVOID value) /* [in] Value to be stored */
{ {
if (index >= NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap) if (index < TLS_MINIMUM_AVAILABLE)
{ {
SetLastError( ERROR_INVALID_PARAMETER ); NtCurrentTeb()->TlsSlots[index] = value;
return FALSE; }
else
{
index -= TLS_MINIMUM_AVAILABLE;
if (index >= 8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (!NtCurrentTeb()->TlsExpansionSlots &&
!(NtCurrentTeb()->TlsExpansionSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits) * sizeof(void*) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
NtCurrentTeb()->TlsExpansionSlots[index] = value;
} }
NtCurrentTeb()->TlsSlots[index] = value;
return TRUE; return TRUE;
} }
......
...@@ -49,6 +49,7 @@ static PEB peb; ...@@ -49,6 +49,7 @@ static PEB peb;
static PEB_LDR_DATA ldr; static PEB_LDR_DATA ldr;
static RTL_USER_PROCESS_PARAMETERS params; /* default parameters if no parent */ static RTL_USER_PROCESS_PARAMETERS params; /* default parameters if no parent */
static RTL_BITMAP tls_bitmap; static RTL_BITMAP tls_bitmap;
static RTL_BITMAP tls_expansion_bitmap;
static LIST_ENTRY tls_links; static LIST_ENTRY tls_links;
...@@ -109,8 +110,11 @@ void thread_init(void) ...@@ -109,8 +110,11 @@ void thread_init(void)
peb.NumberOfProcessors = 1; peb.NumberOfProcessors = 1;
peb.ProcessParameters = &params; peb.ProcessParameters = &params;
peb.TlsBitmap = &tls_bitmap; peb.TlsBitmap = &tls_bitmap;
peb.TlsExpansionBitmap = &tls_expansion_bitmap;
peb.LdrData = &ldr; peb.LdrData = &ldr;
RtlInitializeBitMap( &tls_bitmap, peb.TlsBitmapBits, sizeof(peb.TlsBitmapBits) * 8 ); RtlInitializeBitMap( &tls_bitmap, peb.TlsBitmapBits, sizeof(peb.TlsBitmapBits) * 8 );
RtlInitializeBitMap( &tls_expansion_bitmap, peb.TlsExpansionBitmapBits,
sizeof(peb.TlsExpansionBitmapBits) * 8 );
InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InLoadOrderModuleList );
InitializeListHead( &ldr.InMemoryOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList );
InitializeListHead( &ldr.InInitializationOrderModuleList ); InitializeListHead( &ldr.InInitializationOrderModuleList );
...@@ -535,14 +539,29 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class, ...@@ -535,14 +539,29 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER; if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
index = *(const DWORD *)data; index = *(const DWORD *)data;
if (index >= 64) return STATUS_INVALID_PARAMETER; if (index < TLS_MINIMUM_AVAILABLE)
RtlAcquirePebLock();
for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
{ {
TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks); RtlAcquirePebLock();
teb->TlsSlots[index] = 0; for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
{
TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
teb->TlsSlots[index] = 0;
}
RtlReleasePebLock();
}
else
{
index -= TLS_MINIMUM_AVAILABLE;
if (index >= 8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits))
return STATUS_INVALID_PARAMETER;
RtlAcquirePebLock();
for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
{
TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
if (teb->TlsExpansionSlots) teb->TlsExpansionSlots[index] = 0;
}
RtlReleasePebLock();
} }
RtlReleasePebLock();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
FIXME( "ZeroTlsCell not supported on other threads\n" ); FIXME( "ZeroTlsCell not supported on other threads\n" );
......
...@@ -132,7 +132,7 @@ typedef struct _TEB ...@@ -132,7 +132,7 @@ typedef struct _TEB
DWORD pad9[24]; /* --n f20 */ DWORD pad9[24]; /* --n f20 */
PVOID ReservedForOle; /* -2- f80 used by ole32 (IErrorInfo*) */ PVOID ReservedForOle; /* -2- f80 used by ole32 (IErrorInfo*) */
PVOID pad10[4]; /* --n f84 */ PVOID pad10[4]; /* --n f84 */
PVOID TlsExpansionSlots; /* -2- f94 */ PVOID *TlsExpansionSlots; /* -2- f94 */
} TEB; } TEB;
#endif /* WINE_TEB_DEFINED */ #endif /* WINE_TEB_DEFINED */
......
...@@ -1589,6 +1589,8 @@ extern struct _TEB * WINAPI NtCurrentTeb(void); ...@@ -1589,6 +1589,8 @@ extern struct _TEB * WINAPI NtCurrentTeb(void);
#endif #endif
#define GetFiberData() (*(void **)GetCurrentFiber()) #define GetFiberData() (*(void **)GetCurrentFiber())
#define TLS_MINIMUM_AVAILABLE 64
/* /*
* File formats definitions * File formats definitions
*/ */
......
...@@ -197,7 +197,7 @@ typedef struct _PEB ...@@ -197,7 +197,7 @@ typedef struct _PEB
ULONG ImageProcessAffinityMask; /* c0 */ ULONG ImageProcessAffinityMask; /* c0 */
ULONG GdiHandleBuffer[34]; /* c4 */ ULONG GdiHandleBuffer[34]; /* c4 */
ULONG PostProcessInitRoutine; /* 14c */ ULONG PostProcessInitRoutine; /* 14c */
ULONG TlsExpansionBitmap; /* 150 */ PRTL_BITMAP TlsExpansionBitmap; /* 150 */
ULONG TlsExpansionBitmapBits[32]; /* 154 */ ULONG TlsExpansionBitmapBits[32]; /* 154 */
ULONG SessionId; /* 1d4 */ ULONG SessionId; /* 1d4 */
} PEB, *PPEB; } PEB, *PPEB;
...@@ -235,7 +235,7 @@ typedef struct _TEB ...@@ -235,7 +235,7 @@ typedef struct _TEB
PVOID Reserved4[26]; /* f18 */ PVOID Reserved4[26]; /* f18 */
PVOID ReservedForOle; /* f80 Windows 2000 only */ PVOID ReservedForOle; /* f80 Windows 2000 only */
PVOID Reserved5[4]; /* f84 */ PVOID Reserved5[4]; /* f84 */
PVOID TlsExpansionSlots; /* f94 */ PVOID *TlsExpansionSlots; /* f94 */
} TEB, *PTEB; } TEB, *PTEB;
# endif /* WINE_TEB_DEFINED */ # endif /* WINE_TEB_DEFINED */
#endif /* WINE_NO_TEB */ #endif /* WINE_NO_TEB */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment