Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernelbase/thread.c | 2 +- dlls/ntdll/loader.c | 3 ++- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/thread.c | 10 ++++++++++ include/winternl.h | 1 + 5 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index 0bfef62a7da..f2b746856e1 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -1022,7 +1022,7 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr ) RtlExitUserThread( 1 ); } RtlFreeUserStack( fiber->stack_allocation ); - HeapFree( GetProcessHeap(), 0, fiber->fls_slots ); + RtlProcessFlsData( fiber->fls_slots, 3 ); HeapFree( GetProcessHeap(), 0, fiber ); }
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 20bc3f977d1..cd27ce5658b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3255,7 +3255,8 @@ void WINAPI LdrShutdownThread(void) for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] ); RtlFreeHeap( GetProcessHeap(), 0, pointers ); } - RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots ); + RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 3 ); + NtCurrentTeb()->FlsSlots = NULL; RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); NtCurrentTeb()->TlsExpansionSlots = NULL; RtlReleasePebLock(); diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index ce9f6281d5d..6f44f499825 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -874,6 +874,7 @@ @ stdcall RtlPopFrame(ptr) @ stdcall RtlPrefixString(ptr ptr long) @ stdcall RtlPrefixUnicodeString(ptr ptr long) +@ stdcall RtlProcessFlsData(ptr long) @ stub RtlPropertySetNameToGuid @ stub RtlProtectHeap @ stdcall RtlPushFrame(ptr) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 716ef3b61d0..57292043582 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -343,3 +343,13 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data )
return STATUS_SUCCESS; } + + +/*********************************************************************** + * RtlProcessFlsData (NTDLL.@) + */ +void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags ) +{ + if (flags & 2) + RtlFreeHeap( GetProcessHeap(), 0, teb_fls_data ); +} diff --git a/include/winternl.h b/include/winternl.h index 82328167c9e..75324635ed7 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3480,6 +3480,7 @@ NTSYSAPI NTSTATUS WINAPI RtlPinAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM); NTSYSAPI void WINAPI RtlPopFrame(TEB_ACTIVE_FRAME*); NTSYSAPI BOOLEAN WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN); NTSYSAPI BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN); +NTSYSAPI void WINAPI RtlProcessFlsData(void*,ULONG); NTSYSAPI void WINAPI RtlPushFrame(TEB_ACTIVE_FRAME*); NTSYSAPI NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings(DWORD,HANDLE,const WCHAR*,const WCHAR*,WCHAR*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,ULONG*,ULONG*,WCHAR*,ULONG*);
Win10 18132 introduced increased FLS data limit and entirely changed underlying structure.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernelbase/thread.c | 2 +- dlls/ntdll/loader.c | 6 +- dlls/ntdll/ntdll_misc.h | 3 + dlls/ntdll/thread.c | 244 ++++++++++++++++++++++++++++++++------- include/winternl.h | 28 ++++- 5 files changed, 233 insertions(+), 50 deletions(-)
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index f2b746856e1..ffa05f8fe81 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -762,7 +762,7 @@ struct fiber_data CONTEXT context; /* 14/30 fiber context */ DWORD flags; /* fiber flags */ LPFIBER_START_ROUTINE start; /* start routine */ - void **fls_slots; /* fiber storage slots */ + void *fls_slots; /* fiber storage slots */ };
extern void WINAPI switch_fiber( CONTEXT *old, CONTEXT *new ); diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index cd27ce5658b..1d5ffc33f5d 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -168,7 +168,6 @@ static RTL_CRITICAL_SECTION peb_lock = { &peb_critsect_debug, -1, 0, 0, 0, 0 }; static PEB_LDR_DATA ldr = { sizeof(ldr), TRUE }; static RTL_BITMAP tls_bitmap; static RTL_BITMAP tls_expansion_bitmap; -static RTL_BITMAP fls_bitmap;
static WINE_MODREF *cached_modref; static WINE_MODREF *current_modref; @@ -4005,7 +4004,6 @@ static NTSTATUS process_init(void) peb->FastPebLock = &peb_lock; peb->TlsBitmap = &tls_bitmap; peb->TlsExpansionBitmap = &tls_expansion_bitmap; - peb->FlsBitmap = &fls_bitmap; peb->LoaderLock = &loader_section; peb->OSMajorVersion = 5; peb->OSMinorVersion = 1; @@ -4014,13 +4012,11 @@ static NTSTATUS process_init(void) peb->SessionId = 1; peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL );
- InitializeListHead( &peb->FlsListHead ); RtlInitializeBitMap( &tls_bitmap, peb->TlsBitmapBits, sizeof(peb->TlsBitmapBits) * 8 ); RtlInitializeBitMap( &tls_expansion_bitmap, peb->TlsExpansionBitmapBits, sizeof(peb->TlsExpansionBitmapBits) * 8 ); - RtlInitializeBitMap( &fls_bitmap, peb->FlsBitmapBits, sizeof(peb->FlsBitmapBits) * 8 ); RtlSetBits( peb->TlsBitmap, 0, 1 ); /* TLS index 0 is reserved and should be initialized to NULL. */ - RtlSetBits( peb->FlsBitmap, 0, 1 ); + init_global_fls_data();
InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList ); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 9e905a1bdc0..19bf574a446 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -127,4 +127,7 @@ static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) while (len--) *dst++ = (unsigned char)*src++; }
+/* FLS data */ +extern void init_global_fls_data(void) DECLSPEC_HIDDEN; + #endif diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 57292043582..a4509d82328 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -34,6 +34,7 @@ #include "wine/exception.h"
WINE_DECLARE_DEBUG_CHANNEL(relay); +WINE_DECLARE_DEBUG_CHANNEL(thread);
struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
@@ -253,41 +254,128 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void) ***********************************************************************/
+static GLOBAL_FLS_DATA fls_data; + +#define MAX_FLS_DATA_COUNT 0xff0 + +void DECLSPEC_HIDDEN init_global_fls_data(void) +{ + InitializeListHead( &fls_data.fls_list_head ); +} + +static void lock_fls_data(void) +{ + RtlAcquirePebLock(); +} + +static void unlock_fls_data(void) +{ + RtlReleasePebLock(); +} + +static unsigned int fls_chunk_size( unsigned int chunk_index ) +{ + return 0x10 << chunk_index; +} + +static unsigned int fls_index_from_chunk_index( unsigned int chunk_index, unsigned int index ) +{ + return 0x10 * ((1 << chunk_index) - 1) + index; +} + +static unsigned int fls_chunk_index_from_index( unsigned int index, unsigned int *index_in_chunk ) +{ + unsigned int chunk_index = 0; + + while (index >= fls_chunk_size( chunk_index )) + index -= fls_chunk_size( chunk_index++ ); + + *index_in_chunk = index; + return chunk_index; +} + +static TEB_FLS_DATA * fls_alloc_data(void) +{ + TEB_FLS_DATA *fls; + + if (!(fls = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*fls) ))) + return NULL; + + lock_fls_data(); + InsertTailList( &fls_data.fls_list_head, &fls->fls_list_entry ); + unlock_fls_data(); + + return fls; +} + + /*********************************************************************** * RtlFlsAlloc (NTDLL.@) */ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, ULONG *ret_index ) { - PEB * const peb = NtCurrentTeb()->Peb; - NTSTATUS status = STATUS_NO_MEMORY; - DWORD index; + unsigned int chunk_index, index, i; + FLS_INFO_CHUNK *chunk; + TEB_FLS_DATA *fls;
- RtlAcquirePebLock(); - if (peb->FlsCallback || - (peb->FlsCallback = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, - 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) + if (!(fls = NtCurrentTeb()->FlsSlots) + && !(NtCurrentTeb()->FlsSlots = fls = fls_alloc_data())) + return STATUS_NO_MEMORY; + + lock_fls_data(); + for (i = 0; i < ARRAY_SIZE(fls_data.fls_callback_chunks); ++i) + { + if (!fls_data.fls_callback_chunks[i] || fls_data.fls_callback_chunks[i]->count < fls_chunk_size( i )) + break; + } + + if ((chunk_index = i) == ARRAY_SIZE(fls_data.fls_callback_chunks)) { - index = RtlFindClearBitsAndSet( peb->FlsBitmap, 1, 1 ); - if (index != ~0U) + unlock_fls_data(); + return STATUS_NO_MEMORY; + } + + if ((chunk = fls_data.fls_callback_chunks[chunk_index])) + { + for (index = 0; i < fls_chunk_size( chunk_index ); ++index) + if (!chunk->callbacks[index].callback) + break; + assert( index < fls_chunk_size( chunk_index )); + } + else + { + fls_data.fls_callback_chunks[chunk_index] = chunk = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + offsetof(FLS_INFO_CHUNK, callbacks) + sizeof(*chunk->callbacks) * fls_chunk_size( chunk_index )); + if (!chunk) { - if (!NtCurrentTeb()->FlsSlots && - !(NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, - 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) - { - RtlClearBits( peb->FlsBitmap, index, 1 ); - } - else - { - NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */ - peb->FlsCallback[index] = callback; - status = STATUS_SUCCESS; - } + unlock_fls_data(); + return STATUS_NO_MEMORY; + } + + if (chunk_index) + { + index = 0; + } + else + { + chunk->count = 1; /* FLS index 0 is prohibited. */ + chunk->callbacks[0].callback = (void *)~(ULONG_PTR)0; + index = 1; } } - RtlReleasePebLock(); - if (!status) - *ret_index = index; - return status; + + ++chunk->count; + chunk->callbacks[index].callback = callback ? callback : (void *)~(ULONG_PTR)0; + + if ((*ret_index = fls_index_from_chunk_index( chunk_index, index )) > fls_data.fls_high_index) + fls_data.fls_high_index = *ret_index; + + unlock_fls_data(); + + if (fls->fls_data_chunks[chunk_index]) + fls->fls_data_chunks[chunk_index][index + 1] = NULL; + + return STATUS_SUCCESS; }
@@ -296,20 +384,51 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, */ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) { - NTSTATUS status; + unsigned int chunk_index, idx; + FLS_INFO_CHUNK *chunk; + TEB_FLS_DATA *fls;
- RtlAcquirePebLock(); - if (RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 )) + lock_fls_data(); + + if (!index || index > fls_data.fls_high_index) + { + unlock_fls_data(); + return STATUS_INVALID_PARAMETER; + } + + chunk_index = fls_chunk_index_from_index( index, &idx ); + if (!(chunk = fls_data.fls_callback_chunks[chunk_index]) + || !chunk->callbacks[idx].callback) + { + unlock_fls_data(); + return STATUS_INVALID_PARAMETER; + } + + if ((fls = NtCurrentTeb()->FlsSlots) && fls->fls_data_chunks[chunk_index]) { - RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); /* FIXME: call Fls callback */ - /* FIXME: add equivalent of ThreadZeroTlsCell here */ - if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0; - status = STATUS_SUCCESS; + fls->fls_data_chunks[chunk_index][idx + 1] = NULL; } - else status = STATUS_INVALID_PARAMETER; - RtlReleasePebLock(); - return status; + + --chunk->count; + chunk->callbacks[idx].callback = NULL; + + if (index == fls_data.fls_high_index) + { + while (--fls_data.fls_high_index) + { + if (idx) + --idx; + else + idx = fls_chunk_size( --chunk_index ) - 1; + + if (chunk->callbacks[idx].callback) + break; + } + } + + unlock_fls_data(); + return STATUS_SUCCESS; }
@@ -318,15 +437,25 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) */ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsSetValue( ULONG index, void *data ) { - if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits)) + unsigned int chunk_index, idx; + TEB_FLS_DATA *fls; + + if (!index || index >= MAX_FLS_DATA_COUNT) return STATUS_INVALID_PARAMETER;
- if (!NtCurrentTeb()->FlsSlots && - !(NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, - 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) ))) + if (!(fls = NtCurrentTeb()->FlsSlots) + && !(NtCurrentTeb()->FlsSlots = fls = fls_alloc_data())) + return STATUS_NO_MEMORY; + + chunk_index = fls_chunk_index_from_index( index, &idx ); + + if (!fls->fls_data_chunks[chunk_index] && + !(fls->fls_data_chunks[chunk_index] = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + (fls_chunk_size( chunk_index ) + 1) * sizeof(*fls->fls_data_chunks[chunk_index]) ))) return STATUS_NO_MEMORY;
- NtCurrentTeb()->FlsSlots[index] = data; + fls->fls_data_chunks[chunk_index][idx + 1] = data; + return STATUS_SUCCESS; }
@@ -336,11 +465,15 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsSetValue( ULONG index, void *data ) */ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data ) { - if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) || !NtCurrentTeb()->FlsSlots) + unsigned int chunk_index, idx; + TEB_FLS_DATA *fls; + + if (!index || index >= MAX_FLS_DATA_COUNT || !(fls = NtCurrentTeb()->FlsSlots)) return STATUS_INVALID_PARAMETER;
- *data = NtCurrentTeb()->FlsSlots[index]; + chunk_index = fls_chunk_index_from_index( index, &idx );
+ *data = fls->fls_data_chunks[chunk_index] ? fls->fls_data_chunks[chunk_index][idx + 1] : NULL; return STATUS_SUCCESS; }
@@ -350,6 +483,31 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data ) */ void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags ) { + TEB_FLS_DATA *fls = teb_fls_data; + unsigned int i; + + TRACE_(thread)( "teb_fls_data %p, flags %#x.\n", teb_fls_data, flags ); + + if (flags & ~3) + FIXME_(thread)( "Unknown flags %#x.\n", flags ); + + if (!fls) + return; + + if (flags & 1) + { + lock_fls_data(); + /* Not using RemoveEntryList() as accoring to the test Windows does not zero list entry here. */ + fls->fls_list_entry.Flink->Blink = fls->fls_list_entry.Blink; + fls->fls_list_entry.Blink->Flink = fls->fls_list_entry.Flink; + unlock_fls_data(); + } + if (flags & 2) - RtlFreeHeap( GetProcessHeap(), 0, teb_fls_data ); + { + for (i = 0; i < ARRAY_SIZE(fls->fls_data_chunks); ++i) + RtlFreeHeap( GetProcessHeap(), 0, fls->fls_data_chunks[i] ); + + RtlFreeHeap( GetProcessHeap(), 0, fls ); + } } diff --git a/include/winternl.h b/include/winternl.h index 75324635ed7..89ea58c2d93 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -265,6 +265,32 @@ typedef struct _TEB_ACTIVE_FRAME_EX void *ExtensionIdentifier; } TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX;
+typedef struct _FLS_CALLBACK +{ + void *unknown; + PFLS_CALLBACK_FUNCTION callback; /* ~0 if NULL callback is set, NULL if FLS index is free. */ +} FLS_CALLBACK, *PFLS_CALLBACK; + +typedef struct _FLS_INFO_CHUNK +{ + ULONG count; /* number of allocated FLS indexes in the chunk. */ + FLS_CALLBACK callbacks[1]; /* the size is 0x10 for chunk 0 and is twice as + * the previous chunk size for the rest. */ +} FLS_INFO_CHUNK, *PFLS_INFO_CHUNK; + +typedef struct _GLOBAL_FLS_DATA +{ + FLS_INFO_CHUNK *fls_callback_chunks[8]; + LIST_ENTRY fls_list_head; + ULONG fls_high_index; +} GLOBAL_FLS_DATA, *PGLOBAL_FLS_DATA; + +typedef struct _TEB_FLS_DATA +{ + LIST_ENTRY fls_list_entry; + void **fls_data_chunks[8]; +} TEB_FLS_DATA, *PTEB_FLS_DATA; + #define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED 0x00000001 #define TEB_ACTIVE_FRAME_FLAG_EXTENDED 0x00000001
@@ -446,7 +472,7 @@ typedef struct _TEB ULONG HeapVirtualAffinity; /* fa8/17b0 */ PVOID CurrentTransactionHandle; /* fac/17b8 */ TEB_ACTIVE_FRAME *ActiveFrame; /* fb0/17c0 */ - PVOID *FlsSlots; /* fb4/17c8 */ + TEB_FLS_DATA *FlsSlots; /* fb4/17c8 */ PVOID PreferredLanguages; /* fb8/17d0 */ PVOID UserPrefLanguages; /* fbc/17d8 */ PVOID MergedPrefLanguages; /* fc0/17e0 */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79765
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 222 +++++++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index b15bf468ea5..211fd75cad0 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -41,6 +41,7 @@ static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*); static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG); static NTSTATUS (WINAPI *pRtlFlsSetValue)(ULONG,void *); static NTSTATUS (WINAPI *pRtlFlsGetValue)(ULONG,void **); +static void (WINAPI *pRtlProcessFlsData)(void *fls_data, ULONG flags); static void *fibers[3]; static BYTE testparam = 185; static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES; @@ -74,6 +75,7 @@ static VOID init_funcs(void) X(RtlFlsFree); X(RtlFlsSetValue); X(RtlFlsGetValue); + X(RtlProcessFlsData); #undef X
} @@ -89,6 +91,10 @@ static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData) static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter) { BYTE *tparam = (BYTE *)lpFiberParameter; + TEB *teb = NtCurrentTeb(); + + ok(!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots); + fiberCount++; ok(*tparam == 185, "Parameterdata expected not to be changed\n"); if (fls_index_to_set != FLS_OUT_OF_INDEXES) @@ -96,13 +102,17 @@ static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter) void* ret; BOOL bret;
+ SetLastError( 0xdeadbeef ); ret = pFlsGetValue(fls_index_to_set); ok(ret == NULL, "FlsGetValue returned %p, expected NULL\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %u.\n", GetLastError());
/* Set the FLS value */ bret = pFlsSetValue(fls_index_to_set, fls_value_to_set); ok(bret, "FlsSetValue failed with error %u\n", GetLastError());
+ ok(!!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots); + /* Verify that FlsGetValue retrieves the value set by FlsSetValue */ SetLastError( 0xdeadbeef ); ret = pFlsGetValue(fls_index_to_set); @@ -190,14 +200,59 @@ static void test_FiberHandling(void)
#define FLS_TEST_INDEX_COUNT 4096
+static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found) +{ + unsigned int count = 0; + LIST_ENTRY *entry; + + *index_found = ~0; + + for (entry = le->Flink; entry != le; entry = entry->Flink) + { + if (entry == search_entry) + { + ok(*index_found == ~0, "Duplicate list entry.\n"); + *index_found = count; + } + ++count; + } + return count; +} + +static void WINAPI test_fls_callback(void *data) +{ +} + +static unsigned int test_fls_chunk_size(unsigned int chunk_index) +{ + return 0x10 << chunk_index; +} + +static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned int *index_in_chunk) +{ + unsigned int chunk_index = 0; + + while (index >= test_fls_chunk_size(chunk_index)) + index -= test_fls_chunk_size(chunk_index++); + + *index_in_chunk = index; + return chunk_index; +} + static void test_FiberLocalStorage(void) { static DWORD fls_indices[FLS_TEST_INDEX_COUNT]; - unsigned int i, count; + unsigned int i, j, count, entry_count, index; + LIST_ENTRY *fls_list_head, saved_entry; + TEB_FLS_DATA *fls_data, *new_fls_data; + GLOBAL_FLS_DATA *g_fls_data; + TEB *teb = NtCurrentTeb(); + PEB *peb = teb->Peb; DWORD fls, fls_2; NTSTATUS status; - BOOL ret; + SIZE_T size; void* val; + BOOL ret;
if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree) { @@ -220,7 +275,7 @@ static void test_FiberLocalStorage(void) for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i) { fls_indices[i] = 0xdeadbeef; - status = pRtlFlsAlloc(NULL, &fls_indices[i]); + status = pRtlFlsAlloc(test_fls_callback, &fls_indices[i]); ok(!status || status == STATUS_NO_MEMORY, "Got unexpected status %#x.\n", status); if (status) { @@ -234,9 +289,166 @@ static void test_FiberLocalStorage(void) } } count = i; + + fls_data = teb->FlsSlots; + /* FLS limits are increased since Win10 18312. */ ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count);
+ if (!peb->FlsCallback) + { + ok(pRtlFlsSetValue && pRtlFlsGetValue, "Missing RtlFlsGetValue / RtlFlsSetValue.\n"); + ok(!peb->FlsBitmap, "Got unexpected FlsBitmap %p.\n", peb->FlsBitmap); + ok(!peb->FlsListHead.Flink && !peb->FlsListHead.Blink, "Got nonzero FlsListHead.\n"); + ok(!peb->FlsHighIndex, "Got unexpected FlsHighIndex %u.\n", peb->FlsHighIndex); + + fls_list_head = fls_data->fls_list_entry.Flink; + + entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index); + ok(entry_count == 1, "Got unexpected count %u.\n", entry_count); + ok(!index, "Got unexpected index %u.\n", index); + + g_fls_data = CONTAINING_RECORD(fls_list_head, GLOBAL_FLS_DATA, fls_list_head); + + ok(g_fls_data->fls_high_index == 0xfef, "Got unexpected fls_high_index %#x.\n", g_fls_data->fls_high_index); + + for (i = 0; i < 8; ++i) + { + ok(!!g_fls_data->fls_callback_chunks[i], "Got zero fls_callback_chunks[%u].\n", i); + ok(g_fls_data->fls_callback_chunks[i]->count == test_fls_chunk_size(i), + "Got unexpected g_fls_data->fls_callback_chunks[%u]->count %u.\n", + i, g_fls_data->fls_callback_chunks[i]->count); + + size = HeapSize(GetProcessHeap(), 0, g_fls_data->fls_callback_chunks[i]); + ok(size == sizeof(ULONG_PTR) + sizeof(FLS_CALLBACK) * test_fls_chunk_size(i), + "Got unexpected size %p.\n", (void *)size); + + ok(!!fls_data->fls_data_chunks[i], "Got zero fls_data->fls_data_chunks[%u].\n", i); + ok(!fls_data->fls_data_chunks[i][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n", + i, fls_data->fls_data_chunks[i][0]); + size = HeapSize(GetProcessHeap(), 0, fls_data->fls_data_chunks[i]); + ok(size == sizeof(void *) * (test_fls_chunk_size(i) + 1), "Got unexpected size %p.\n", (void *)size); + + if (!i) + { + ok(g_fls_data->fls_callback_chunks[0]->callbacks[0].callback == (void *)~(ULONG_PTR)0, + "Got unexpected callback %p.\n", + g_fls_data->fls_callback_chunks[0]->callbacks[0].callback); + } + + for (j = i ? 0 : fls_indices[0]; j < test_fls_chunk_size(i); ++j) + { + ok(!g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown, + "Got unexpected unknown %p, i %u, j %u.\n", + g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown, i, j); + ok(g_fls_data->fls_callback_chunks[i]->callbacks[j].callback == test_fls_callback, + "Got unexpected callback %p, i %u, j %u.\n", + g_fls_data->fls_callback_chunks[i]->callbacks[j].callback, i, j); + } + } + for (i = 0; i < count; ++i) + { + j = test_fls_chunk_index_from_index(fls_indices[i], &index); + ok(fls_data->fls_data_chunks[j][index + 1] == (void *)(ULONG_PTR)(i + 1), + "Got unexpected FLS value %p, i %u, j %u, index %u.\n", + fls_data->fls_data_chunks[j][index + 1], i, j, index); + } + j = test_fls_chunk_index_from_index(fls_indices[0x10], &index); + g_fls_data->fls_callback_chunks[j]->callbacks[index].callback = NULL; + status = pRtlFlsFree(fls_indices[0x10]); + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + + g_fls_data->fls_callback_chunks[j]->callbacks[index].callback = test_fls_callback; + status = pRtlFlsFree(fls_indices[0x10]); + ok(!status, "Got unexpected status %#x.\n", status); + + ok(!fls_data->fls_data_chunks[j][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n", + j, fls_data->fls_data_chunks[j][0]); + ok(!g_fls_data->fls_callback_chunks[j]->callbacks[index].callback, + "Got unexpected callback %p.\n", + g_fls_data->fls_callback_chunks[j]->callbacks[index].callback); + + status = pRtlFlsAlloc(test_fls_callback, &index); + ok(!status, "Got unexpected status %#x.\n", status); + ok(index == fls_indices[0x10], "Got unexpected index %u.\n", index); + status = pRtlFlsSetValue(index, (void *)(ULONG_PTR)0x11); + ok(!status, "Got unexpected status %#x.\n", status); + + teb->FlsSlots = NULL; + + val = (void *)0xdeadbeef; + status = pRtlFlsGetValue(fls_indices[1], &val); + new_fls_data = teb->FlsSlots; + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + ok(val == (void *)0xdeadbeef, "Got unexpected val %p.\n", val); + ok(!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data); + + status = pRtlFlsSetValue(fls_indices[1], NULL); + new_fls_data = teb->FlsSlots; + ok(!status, "Got unexpected status %#x.\n", status); + ok(!!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data); + + entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index); + ok(entry_count == 2, "Got unexpected count %u.\n", entry_count); + ok(!index, "Got unexpected index %u.\n", index); + check_linked_list(fls_list_head, &new_fls_data->fls_list_entry, &index); + ok(index == 1, "Got unexpected index %u.\n", index); + + val = (void *)0xdeadbeef; + status = pRtlFlsGetValue(fls_indices[2], &val); + ok(!status, "Got unexpected status %#x.\n", status); + ok(!val, "Got unexpected val %p.\n", val); + + + /* Looks like with bit 0 of RtlProcessFlsData flags is responsible for removing FLS data + * from the linked list and bit 1 for freeing memory, the remaining bits do not have any + * obvious effect. */ + for (i = 2; i < 32; ++i) + { + pRtlProcessFlsData(new_fls_data, 1 << i); + size = HeapSize(GetProcessHeap(), 0, new_fls_data); + ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size); + } + + if (0) + { + pRtlProcessFlsData(new_fls_data, 2); + entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index); + ok(entry_count == 2, "Got unexpected count %u.\n", entry_count); + + /* Crashes on Windows. */ + HeapSize(GetProcessHeap(), 0, new_fls_data); + } + + saved_entry = new_fls_data->fls_list_entry; + teb->FlsSlots = NULL; + pRtlProcessFlsData(new_fls_data, 1); + ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots); + teb->FlsSlots = fls_data; + + ok(new_fls_data->fls_list_entry.Flink == saved_entry.Flink, "Got unexpected Flink %p.\n", + saved_entry.Flink); + ok(new_fls_data->fls_list_entry.Blink == saved_entry.Blink, "Got unexpected Flink %p.\n", + saved_entry.Blink); + + size = HeapSize(GetProcessHeap(), 0, new_fls_data); + ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size); + pRtlProcessFlsData(new_fls_data, 2); + if (0) + { + /* crashes on Windows. */ + HeapSize(GetProcessHeap(), 0, new_fls_data); + } + + entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index); + ok(entry_count == 1, "Got unexpected count %u.\n", entry_count); + ok(!index, "Got unexpected index %u.\n", index); + } + else + { + win_skip("Old FLS data storage layout, skipping test.\n"); + } + if (0) { /* crashes on Windows. */ @@ -249,11 +461,11 @@ static void test_FiberLocalStorage(void) { status = pRtlFlsGetValue(fls_indices[i], &val); ok(!status, "Got unexpected status %#x.\n", status); - ok(val == (void *)(ULONG_PTR)(i + 1), "Got unexpected val %p.\n", val); + ok(val == (void *)(ULONG_PTR)(i + 1), "Got unexpected val %p, i %u.\n", val, i); }
status = pRtlFlsFree(fls_indices[i]); - ok(!status, "Got unexpected status %#x.\n", status); + ok(!status, "Got unexpected status %#x, i %u.\n", status, i); } } else
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79766
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/loader.c | 3 +-- dlls/ntdll/loader.c | 2 ++ dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/thread.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index fecbee3ba1a..8e8834239ba 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -2629,8 +2629,7 @@ todo_wine SetLastError(0xdeadbeef); value = pFlsGetValue(fls_index); ok(!value, "FlsGetValue returned %p, expected NULL\n", value); - todo_wine - ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); + ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); ret = pFlsSetValue(fls_index, (void*) 0x31415); ok(ret, "FlsSetValue failed\n"); fls_count++; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 1d5ffc33f5d..8374dd97326 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3511,6 +3511,8 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks ); RtlReleasePebLock();
+ NtCurrentTeb()->FlsSlots = fls_alloc_data(); + if (!attach_done) /* first time around */ { attach_done = 1; diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 19bf574a446..8cc3a154fe2 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -129,5 +129,6 @@ static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
/* FLS data */ extern void init_global_fls_data(void) DECLSPEC_HIDDEN; +TEB_FLS_DATA * fls_alloc_data(void) DECLSPEC_HIDDEN;
#endif diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index a4509d82328..8d44a96a4c8 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -294,7 +294,7 @@ static unsigned int fls_chunk_index_from_index( unsigned int index, unsigned int return chunk_index; }
-static TEB_FLS_DATA * fls_alloc_data(void) +TEB_FLS_DATA * DECLSPEC_HIDDEN fls_alloc_data(void) { TEB_FLS_DATA *fls;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79767
Your paranoid android.
=== w10pro64_ar (32 bit report) ===
kernel32: loader.c:2763: Test failed: attached thread count should be 2 loader.c:708: Test failed: 1196: wrong status c000011b/c0000130 loader.c:708: Test failed: 1201: wrong status c000011b/c0000130 loader.c:708: Test failed: 1206: wrong status c000011b/c000007b loader.c:708: Test failed: 1211: wrong status c000011b/c000007b loader.c:708: Test failed: 1216: wrong status c000011b/c000007b loader.c:708: Test failed: 1221: wrong status c000011b/c000007b loader.c:708: Test failed: 1226: wrong status c000011b/c000007b loader.c:708: Test failed: 1242: wrong status c000011b/0 loader.c:708: Test failed: 1246: wrong status c000011b/0 loader.c:708: Test failed: 1251: wrong status c000011b/0 loader.c:708: Test failed: 1255: wrong status c000011b/0 loader.c:708: Test failed: 1259: wrong status c000011b/0 loader.c:708: Test failed: 1298: wrong status c000011b/c000007b loader.c:708: Test failed: 1307: wrong status c000011b/c000007b loader.c:708: Test failed: 1312: wrong status c000011b/0 loader.c:711: Test failed: 1312: failed with c000011b expected fallback loader.c:708: Test failed: 1319: wrong status c000011b/0 loader.c:711: Test failed: 1319: failed with c000011b expected fallback loader.c:708: Test failed: 1326: wrong status c000011b/0 loader.c:711: Test failed: 1326: failed with c000011b expected fallback loader.c:708: Test failed: 1334: wrong status c000011b/0 loader.c:711: Test failed: 1334: failed with c000011b expected fallback loader.c:708: Test failed: 1341: wrong status c000011b/0 loader.c:711: Test failed: 1341: failed with c000011b expected fallback loader.c:708: Test failed: 1351: wrong status c000011b/0 loader.c:708: Test failed: 1356: wrong status c000011b/0 loader.c:708: Test failed: 1361: wrong status c000011b/0 loader.c:708: Test failed: 1366: wrong status c000011b/0 loader.c:708: Test failed: 1371: wrong status c000011b/0
=== w10pro64_ja (32 bit report) ===
kernel32: loader.c:2763: Test failed: attached thread count should be 2
=== w10pro64_zh_CN (32 bit report) ===
kernel32: loader.c:2763: Test failed: attached thread count should be 2
=== w10pro64_2scr (64 bit report) ===
kernel32: loader.c:708: Test failed: 1196: wrong status c000011b/c0000130 loader.c:708: Test failed: 1201: wrong status c000011b/c0000130 loader.c:708: Test failed: 1206: wrong status c000011b/c000007b loader.c:708: Test failed: 1211: wrong status c000011b/c000007b loader.c:708: Test failed: 1216: wrong status c000011b/c000007b loader.c:708: Test failed: 1221: wrong status c000011b/c000007b loader.c:708: Test failed: 1226: wrong status c000011b/c000007b loader.c:708: Test failed: 1242: wrong status c000011b/0 loader.c:708: Test failed: 1246: wrong status c000011b/0 loader.c:708: Test failed: 1251: wrong status c000011b/0 loader.c:708: Test failed: 1255: wrong status c000011b/0 loader.c:708: Test failed: 1259: wrong status c000011b/0 loader.c:708: Test failed: 1413: wrong status c000011b/c000007b loader.c:708: Test failed: 1421: wrong status c000011b/c000007b loader.c:708: Test failed: 1426: wrong status c000011b/0 loader.c:711: Test failed: 1426: failed with c000011b expected fallback loader.c:708: Test failed: 1432: wrong status c000011b/0 loader.c:711: Test failed: 1432: failed with c000011b expected fallback loader.c:708: Test failed: 1438: wrong status c000011b/0 loader.c:711: Test failed: 1438: failed with c000011b expected fallback loader.c:708: Test failed: 1445: wrong status c000011b/0 loader.c:711: Test failed: 1445: failed with c000011b expected fallback loader.c:708: Test failed: 1451: wrong status c000011b/0 loader.c:708: Test failed: 1460: wrong status c000011b/0 loader.c:708: Test failed: 1464: wrong status c000011b/0 loader.c:708: Test failed: 1468: wrong status c000011b/0 loader.c:708: Test failed: 1472: wrong status c000011b/0 loader.c:708: Test failed: 1476: wrong status c000011b/0
=== w10pro64_ja (64 bit report) ===
kernel32: loader.c:708: Test failed: 1196: wrong status c000011b/c0000130 loader.c:708: Test failed: 1201: wrong status c000011b/c0000130 loader.c:708: Test failed: 1206: wrong status c000011b/c000007b loader.c:708: Test failed: 1211: wrong status c000011b/c000007b loader.c:708: Test failed: 1216: wrong status c000011b/c000007b loader.c:708: Test failed: 1221: wrong status c000011b/c000007b loader.c:708: Test failed: 1226: wrong status c000011b/c000007b loader.c:708: Test failed: 1242: wrong status c000011b/0 loader.c:708: Test failed: 1246: wrong status c000011b/0 loader.c:708: Test failed: 1251: wrong status c000011b/0 loader.c:708: Test failed: 1255: wrong status c000011b/0 loader.c:708: Test failed: 1259: wrong status c000011b/0 loader.c:708: Test failed: 1413: wrong status c000011b/c000007b loader.c:708: Test failed: 1421: wrong status c000011b/c000007b loader.c:708: Test failed: 1426: wrong status c000011b/0 loader.c:711: Test failed: 1426: failed with c000011b expected fallback loader.c:708: Test failed: 1432: wrong status c000011b/0 loader.c:711: Test failed: 1432: failed with c000011b expected fallback loader.c:708: Test failed: 1438: wrong status c000011b/0 loader.c:711: Test failed: 1438: failed with c000011b expected fallback loader.c:708: Test failed: 1445: wrong status c000011b/0 loader.c:711: Test failed: 1445: failed with c000011b expected fallback loader.c:708: Test failed: 1451: wrong status c000011b/0 loader.c:708: Test failed: 1460: wrong status c000011b/0 loader.c:708: Test failed: 1464: wrong status c000011b/0 loader.c:708: Test failed: 1468: wrong status c000011b/0 loader.c:708: Test failed: 1472: wrong status c000011b/0 loader.c:708: Test failed: 1476: wrong status c000011b/0
=== w10pro64_zh_CN (64 bit report) ===
kernel32: loader.c:708: Test failed: 1179: wrong status c000011b/c0000131 loader.c:708: Test failed: 1179: wrong status c000011b/c0000130 loader.c:708: Test failed: 1196: wrong status c000011b/c0000130 loader.c:708: Test failed: 1201: wrong status c000011b/c0000130 loader.c:708: Test failed: 1206: wrong status c000011b/c000007b loader.c:708: Test failed: 1211: wrong status c000011b/c000007b loader.c:708: Test failed: 1216: wrong status c000011b/c000007b loader.c:708: Test failed: 1221: wrong status c000011b/c000007b loader.c:708: Test failed: 1226: wrong status c000011b/c000007b loader.c:708: Test failed: 1242: wrong status c000011b/0 loader.c:708: Test failed: 1246: wrong status c000011b/0 loader.c:708: Test failed: 1251: wrong status c000011b/0 loader.c:708: Test failed: 1255: wrong status c000011b/0 loader.c:708: Test failed: 1259: wrong status c000011b/0 loader.c:708: Test failed: 1413: wrong status c000011b/c000007b loader.c:708: Test failed: 1421: wrong status c000011b/c000007b loader.c:708: Test failed: 1426: wrong status c000011b/0 loader.c:711: Test failed: 1426: failed with c000011b expected fallback loader.c:708: Test failed: 1432: wrong status c000011b/0 loader.c:711: Test failed: 1432: failed with c000011b expected fallback loader.c:708: Test failed: 1438: wrong status c000011b/0 loader.c:711: Test failed: 1438: failed with c000011b expected fallback loader.c:708: Test failed: 1445: wrong status c000011b/0 loader.c:711: Test failed: 1445: failed with c000011b expected fallback loader.c:708: Test failed: 1451: wrong status c000011b/0 loader.c:708: Test failed: 1460: wrong status c000011b/0 loader.c:708: Test failed: 1464: wrong status c000011b/0 loader.c:708: Test failed: 1468: wrong status c000011b/0 loader.c:708: Test failed: 1472: wrong status c000011b/0 loader.c:708: Test failed: 1476: wrong status c000011b/0
=== debiant (32 bit report) ===
kernel32: loader.c:3929: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 60380 / 60080 loader.c:3934: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 1388e / 13822 loader.c:3934: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b88 / 3b6c loader.c:3939: Test failed: ntdll.dll: wrong section 0 loader.c:3939: Test failed: ntdll.dll: wrong section 1 loader.c:3939: Test failed: ntdll.dll: wrong section 2 loader.c:3939: Test failed: ntdll.dll: wrong section 3 loader.c:3939: Test failed: ntdll.dll: wrong section 4 loader.c:3939: Test failed: ntdll.dll: wrong section 5 loader.c:3939: Test failed: ntdll.dll: wrong section 8 loader.c:3939: Test failed: ntdll.dll: wrong section 10 loader.c:3939: Test failed: ntdll.dll: wrong section 11 loader.c:3939: Test failed: ntdll.dll: wrong section 12 loader.c:3939: Test failed: ntdll.dll: wrong section 13 loader.c:3939: Test failed: ntdll.dll: wrong section 14 loader.c:3939: Test failed: ntdll.dll: wrong section 15 loader.c:3939: Test failed: kernel32.dll: wrong section 10 loader.c:3939: Test failed: kernel32.dll: wrong section 11 loader.c:3939: Test failed: kernel32.dll: wrong section 12 loader.c:3939: Test failed: kernel32.dll: wrong section 13 loader.c:3939: Test failed: kernel32.dll: wrong section 14 loader.c:3939: Test failed: kernel32.dll: wrong section 15 loader.c:3939: Test failed: advapi32.dll: wrong section 10 loader.c:3939: Test failed: user32.dll: wrong section 10 loader.c:3939: Test failed: user32.dll: wrong section 11 loader.c:3939: Test failed: user32.dll: wrong section 12 loader.c:3939: Test failed: user32.dll: wrong section 13 loader.c:3939: Test failed: user32.dll: wrong section 14 loader.c:3939: Test failed: user32.dll: wrong section 15
=== debiant (build log) ===
The task timed out
=== debiant (32 bit WoW report) ===
kernel32: loader.c:3929: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 60380 / 60080 loader.c:3934: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 1388e / 13822 loader.c:3934: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b88 / 3b6c loader.c:3939: Test failed: ntdll.dll: wrong section 0 loader.c:3939: Test failed: ntdll.dll: wrong section 1 loader.c:3939: Test failed: ntdll.dll: wrong section 2 loader.c:3939: Test failed: ntdll.dll: wrong section 3 loader.c:3939: Test failed: ntdll.dll: wrong section 4 loader.c:3939: Test failed: ntdll.dll: wrong section 5 loader.c:3939: Test failed: ntdll.dll: wrong section 8 loader.c:3939: Test failed: ntdll.dll: wrong section 10 loader.c:3939: Test failed: ntdll.dll: wrong section 11 loader.c:3939: Test failed: ntdll.dll: wrong section 12 loader.c:3939: Test failed: ntdll.dll: wrong section 13 loader.c:3939: Test failed: ntdll.dll: wrong section 14 loader.c:3939: Test failed: ntdll.dll: wrong section 15 loader.c:3939: Test failed: kernel32.dll: wrong section 10 loader.c:3939: Test failed: kernel32.dll: wrong section 11 loader.c:3939: Test failed: kernel32.dll: wrong section 12 loader.c:3939: Test failed: kernel32.dll: wrong section 13 loader.c:3939: Test failed: kernel32.dll: wrong section 14 loader.c:3939: Test failed: kernel32.dll: wrong section 15 loader.c:3939: Test failed: advapi32.dll: wrong section 10 loader.c:3939: Test failed: user32.dll: wrong section 10 loader.c:3939: Test failed: user32.dll: wrong section 11 loader.c:3939: Test failed: user32.dll: wrong section 12 loader.c:3939: Test failed: user32.dll: wrong section 13 loader.c:3939: Test failed: user32.dll: wrong section 14 loader.c:3939: Test failed: user32.dll: wrong section 15
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 36 +++++++++++++++++++++++++++++++++--- dlls/ntdll/thread.c | 13 +++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index 211fd75cad0..889ce785fab 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -37,6 +37,8 @@ static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); static BOOL (WINAPI *pFlsFree)(DWORD); static PVOID (WINAPI *pFlsGetValue)(DWORD); static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); +static void (WINAPI *pRtlAcquirePebLock)(void); +static void (WINAPI *pRtlReleasePebLock)(void); static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*); static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG); static NTSTATUS (WINAPI *pRtlFlsSetValue)(ULONG,void *); @@ -76,6 +78,8 @@ static VOID init_funcs(void) X(RtlFlsSetValue); X(RtlFlsGetValue); X(RtlProcessFlsData); + X(RtlAcquirePebLock); + X(RtlReleasePebLock); #undef X
} @@ -239,6 +243,19 @@ static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned return chunk_index; }
+static HANDLE test_fiberlocalstorage_peb_locked_event; +static HANDLE test_fiberlocalstorage_done_event; + + +static DWORD WINAPI test_FiberLocalStorage_thread(void *arg) +{ + pRtlAcquirePebLock(); + SetEvent(test_fiberlocalstorage_peb_locked_event); + WaitForSingleObject(test_fiberlocalstorage_done_event, INFINITE); + pRtlReleasePebLock(); + return 0; +} + static void test_FiberLocalStorage(void) { static DWORD fls_indices[FLS_TEST_INDEX_COUNT]; @@ -246,10 +263,11 @@ static void test_FiberLocalStorage(void) LIST_ENTRY *fls_list_head, saved_entry; TEB_FLS_DATA *fls_data, *new_fls_data; GLOBAL_FLS_DATA *g_fls_data; + DWORD fls, fls_2, result; TEB *teb = NtCurrentTeb(); PEB *peb = teb->Peb; - DWORD fls, fls_2; NTSTATUS status; + HANDLE hthread; SIZE_T size; void* val; BOOL ret; @@ -420,17 +438,29 @@ static void test_FiberLocalStorage(void) HeapSize(GetProcessHeap(), 0, new_fls_data); }
- saved_entry = new_fls_data->fls_list_entry; + test_fiberlocalstorage_peb_locked_event = CreateEventA(NULL, FALSE, FALSE, NULL); + test_fiberlocalstorage_done_event = CreateEventA(NULL, FALSE, FALSE, NULL); + hthread = CreateThread(NULL, 0, test_FiberLocalStorage_thread, NULL, 0, NULL); + ok(!!hthread, "CreateThread failed.\n"); + result = WaitForSingleObject(test_fiberlocalstorage_peb_locked_event, INFINITE); + ok(result == WAIT_OBJECT_0, "Got unexpected result %u.\n", result); teb->FlsSlots = NULL; + + saved_entry = new_fls_data->fls_list_entry; pRtlProcessFlsData(new_fls_data, 1); ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots); + teb->FlsSlots = fls_data; + SetEvent(test_fiberlocalstorage_done_event); + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); + CloseHandle(test_fiberlocalstorage_peb_locked_event); + CloseHandle(test_fiberlocalstorage_done_event);
ok(new_fls_data->fls_list_entry.Flink == saved_entry.Flink, "Got unexpected Flink %p.\n", saved_entry.Flink); ok(new_fls_data->fls_list_entry.Blink == saved_entry.Blink, "Got unexpected Flink %p.\n", saved_entry.Blink); - size = HeapSize(GetProcessHeap(), 0, new_fls_data); ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size); pRtlProcessFlsData(new_fls_data, 2); diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 8d44a96a4c8..252e4ed0e0b 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -256,6 +256,15 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void)
static GLOBAL_FLS_DATA fls_data;
+static RTL_CRITICAL_SECTION fls_section; +static RTL_CRITICAL_SECTION_DEBUG fls_critsect_debug = +{ + 0, 0, &fls_section, + { &fls_critsect_debug.ProcessLocksList, &fls_critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": fls_section") } +}; +static RTL_CRITICAL_SECTION fls_section = { &fls_critsect_debug, -1, 0, 0, 0, 0 }; + #define MAX_FLS_DATA_COUNT 0xff0
void DECLSPEC_HIDDEN init_global_fls_data(void) @@ -265,12 +274,12 @@ void DECLSPEC_HIDDEN init_global_fls_data(void)
static void lock_fls_data(void) { - RtlAcquirePebLock(); + RtlEnterCriticalSection( &fls_section ); }
static void unlock_fls_data(void) { - RtlReleasePebLock(); + RtlLeaveCriticalSection( &fls_section ); }
static unsigned int fls_chunk_size( unsigned int chunk_index )
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79768
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79764
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out