Added ntdll-FLS_Callbacks patchset.

This commit is contained in:
Paul Gofman 2020-04-25 12:44:30 +03:00
parent 4581daea3b
commit a8b95783eb
8 changed files with 728 additions and 0 deletions

View File

@ -0,0 +1,322 @@
From 5c370d9f0be803d89302da7471ef0b93b45a0d75 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 14:32:23 +0300
Subject: [PATCH] kernelbase: Maintain FLS storage list in PEB.
---
dlls/kernel32/tests/fiber.c | 35 ++++++++++++++++++++
dlls/kernel32/tests/thread.c | 2 --
dlls/kernelbase/thread.c | 63 +++++++++++++++++++++++++++---------
dlls/ntdll/loader.c | 46 ++++++++++++++++++++++++++
4 files changed, 129 insertions(+), 17 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c
index 7501165dc87..2bcc3ee60c4 100644
--- a/dlls/kernel32/tests/fiber.c
+++ b/dlls/kernel32/tests/fiber.c
@@ -19,6 +19,7 @@
*/
#include "wine/test.h"
+#include <winternl.h>
static LPVOID (WINAPI *pCreateFiber)(SIZE_T,LPFIBER_START_ROUTINE,LPVOID);
static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID);
@@ -171,8 +172,25 @@ static void test_FiberHandling(void)
if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
}
+static unsigned int list_size(const LIST_ENTRY *le)
+{
+ unsigned int count = 0;
+ LIST_ENTRY *entry;
+
+ for (entry = le->Flink; entry != le; entry = entry->Flink)
+ ++count;
+
+ return count;
+}
+
+#define FLS_TEST_INDEX_COUNT 2048
+
static void test_FiberLocalStorage(void)
{
+ static DWORD fls_indices[FLS_TEST_INDEX_COUNT];
+ TEB *teb = NtCurrentTeb();
+ unsigned int i, count;
+ PEB *peb = teb->Peb;
DWORD fls, fls_2;
BOOL ret;
void* val;
@@ -183,6 +201,23 @@ static void test_FiberLocalStorage(void)
return;
}
+ ok(!!teb->FlsSlots, "Got NULL teb->FlsSlots.\n");
+ ok(!!peb->FlsCallback, "Got NULL peb->FlsCallback.\n");
+
+ count = list_size(&peb->FlsListHead);
+ ok(count == 1, "Got unexpected FLS list size %u.\n", count);
+
+ for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i)
+ {
+ if ((fls_indices[i] = pFlsAlloc(NULL)) == FLS_OUT_OF_INDEXES)
+ break;
+ }
+ count = i;
+ ok(count <= 127, "Could allocate %u FLS indices.\n", count);
+
+ for (i = 0; i < count; ++i)
+ pFlsFree(fls_indices[i]);
+
/* Test an unallocated index
* FlsFree should fail
* FlsGetValue and FlsSetValue should succeed
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index a454bf118cc..dac30959734 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -2435,7 +2435,6 @@ START_TEST(thread)
}
return;
}
-
test_thread_info();
test_reserved_tls();
test_CreateRemoteThread();
@@ -2463,6 +2462,5 @@ START_TEST(thread)
test_thread_fpu_cw();
test_thread_actctx();
test_thread_description();
-
test_threadpool();
}
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 03b16da95bb..4409f120491 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -38,6 +38,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(thread);
+static inline void **fls_addr_from_index(void *fls_slots, DWORD index)
+{
+ return (void **)((BYTE *)fls_slots + sizeof(LIST_ENTRY)) + index;
+}
/***********************************************************************
* Threads
@@ -916,6 +920,19 @@ static void init_fiber_context( struct fiber_data *fiber )
#endif
}
+typedef void WINAPI (*FLS_LOCK_FUNCTION)(void *);
+
+static void lock_fls_section(void)
+{
+ if (NtCurrentTeb()->Peb->FlsCallback)
+ ((FLS_LOCK_FUNCTION)NtCurrentTeb()->Peb->FlsCallback[0])(NULL);
+}
+
+static void unlock_fls_section(void)
+{
+ if (NtCurrentTeb()->Peb->FlsCallback)
+ ((FLS_LOCK_FUNCTION)NtCurrentTeb()->Peb->FlsCallback[1])(NULL);
+}
/***********************************************************************
* CreateFiber (kernelbase.@)
@@ -1023,7 +1040,16 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr )
RtlExitUserThread( 1 );
}
RtlFreeUserStack( fiber->stack_allocation );
- HeapFree( GetProcessHeap(), 0, fiber->fls_slots );
+
+ if (fiber->fls_slots)
+ {
+ lock_fls_section();
+ RemoveEntryList( (LIST_ENTRY *)fiber->fls_slots );
+ unlock_fls_section();
+
+ HeapFree( GetProcessHeap(), 0, fiber->fls_slots );
+ }
+
HeapFree( GetProcessHeap(), 0, fiber );
}
@@ -1045,6 +1071,19 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber )
struct fiber_data *new_fiber = fiber;
struct fiber_data *current_fiber = NtCurrentTeb()->Tib.u.FiberData;
+ if (!new_fiber->fls_slots)
+ {
+ TEB *teb = NtCurrentTeb();
+ PEB *peb = teb->Peb;
+
+ new_fiber->fls_slots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(LIST_ENTRY) + 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) );
+
+ lock_fls_section();
+ InsertTailList(&peb->FlsListHead, (LIST_ENTRY *)new_fiber->fls_slots);
+ unlock_fls_section();
+ }
+
current_fiber->except = NtCurrentTeb()->Tib.ExceptionList;
current_fiber->stack_limit = NtCurrentTeb()->Tib.StackLimit;
current_fiber->fls_slots = NtCurrentTeb()->FlsSlots;
@@ -1070,9 +1109,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
PEB * const peb = NtCurrentTeb()->Peb;
RtlAcquirePebLock();
- if (!peb->FlsCallback &&
- !(peb->FlsCallback = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) )))
+ if (!peb->FlsCallback)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
index = FLS_OUT_OF_INDEXES;
@@ -1082,9 +1119,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
index = RtlFindClearBitsAndSet( peb->FlsBitmap, 1, 1 );
if (index != ~0U)
{
- if (!NtCurrentTeb()->FlsSlots &&
- !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) )))
+ if (!NtCurrentTeb()->FlsSlots)
{
RtlClearBits( peb->FlsBitmap, index, 1 );
index = FLS_OUT_OF_INDEXES;
@@ -1092,8 +1127,8 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
}
else
{
- NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */
- peb->FlsCallback[index] = callback;
+ *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL; /* clear the value */
+ peb->FlsCallback[index + 2] = callback;
}
}
else SetLastError( ERROR_NO_MORE_ITEMS );
@@ -1117,7 +1152,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index )
{
/* FIXME: call Fls callback */
/* FIXME: add equivalent of ThreadZeroTlsCell here */
- if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0;
+ if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL;
}
else SetLastError( ERROR_INVALID_PARAMETER );
RtlReleasePebLock();
@@ -1136,7 +1171,7 @@ PVOID WINAPI DECLSPEC_HOTPATCH FlsGetValue( DWORD index )
return NULL;
}
SetLastError( ERROR_SUCCESS );
- return NtCurrentTeb()->FlsSlots[index];
+ return *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index);
}
@@ -1150,14 +1185,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsSetValue( DWORD index, PVOID data )
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
- if (!NtCurrentTeb()->FlsSlots &&
- !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) )))
+ if (!NtCurrentTeb()->FlsSlots)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
- NtCurrentTeb()->FlsSlots[index] = data;
+ *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = data;
return TRUE;
}
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 5e8de8821dd..71ef1cfea0a 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -179,6 +179,15 @@ static CRITICAL_SECTION_DEBUG dlldir_critsect_debug =
};
static CRITICAL_SECTION dlldir_section = { &dlldir_critsect_debug, -1, 0, 0, 0, 0 };
+static CRITICAL_SECTION fls_section;
+static 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 CRITICAL_SECTION fls_section = { &fls_critsect_debug, -1, 0, 0, 0, 0 };;
+
static WINE_MODREF *cached_modref;
static WINE_MODREF *current_modref;
static WINE_MODREF *last_failed_modref;
@@ -219,6 +228,16 @@ static RTL_UNLOAD_EVENT_TRACE unload_traces[RTL_UNLOAD_EVENT_TRACE_NUMBER];
static RTL_UNLOAD_EVENT_TRACE *unload_trace_ptr;
static unsigned int unload_trace_seq;
+static void WINAPI lock_fls_section( PVOID dummy )
+{
+ RtlEnterCriticalSection( &fls_section );
+}
+
+static void WINAPI unlock_fls_section( PVOID dummy )
+{
+ RtlLeaveCriticalSection( &fls_section );
+}
+
static void module_push_unload_trace( const LDR_DATA_TABLE_ENTRY *ldr )
{
RTL_UNLOAD_EVENT_TRACE *ptr = &unload_traces[unload_trace_seq];
@@ -3913,6 +3932,13 @@ void WINAPI LdrShutdownThread(void)
/* don't do any detach calls if process is exiting */
if (process_detaching) return;
+ if (NtCurrentTeb()->FlsSlots)
+ {
+ lock_fls_section( NULL );
+ RemoveEntryList( (LIST_ENTRY *)NtCurrentTeb()->FlsSlots );
+ unlock_fls_section( NULL );
+ }
+
RtlEnterCriticalSection( &loader_section );
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
@@ -4153,6 +4179,7 @@ static void user_shared_data_init(void)
*/
void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknown3, ULONG_PTR unknown4 )
{
+ static const unsigned int fls_slot_count = 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits);
static const LARGE_INTEGER zero;
static int attach_done;
int i;
@@ -4191,6 +4218,25 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknow
InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
RtlReleasePebLock();
+ if (!NtCurrentTeb()->Peb->FlsCallback)
+ {
+ NtCurrentTeb()->Peb->FlsCallback = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ (fls_slot_count + 2) * sizeof(void*) );
+ if (!NtCurrentTeb()->Peb->FlsCallback)
+ ERR( "No memory for FLS callbacks.\n" );
+
+ if (NtCurrentTeb()->Peb->FlsCallback)
+ {
+ NtCurrentTeb()->Peb->FlsCallback[0] = lock_fls_section;
+ NtCurrentTeb()->Peb->FlsCallback[1] = unlock_fls_section;
+ }
+ }
+ NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(LIST_ENTRY) + fls_slot_count * sizeof(void*) );
+ lock_fls_section( NULL );
+ InsertTailList(&NtCurrentTeb()->Peb->FlsListHead, (LIST_ENTRY *)NtCurrentTeb()->FlsSlots);
+ unlock_fls_section( NULL );
+
if (!attach_done) /* first time around */
{
attach_done = 1;
--
2.25.3

View File

@ -0,0 +1,52 @@
From 55dbeff93ce46bfba9beaea7b9a67ba7fcd6df88 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 19:44:32 +0300
Subject: [PATCH] kernelbase: Don't use PEB lock for FLS data.
---
dlls/kernelbase/thread.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 4409f120491..0ba67e1b6c9 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -1108,7 +1108,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
DWORD index;
PEB * const peb = NtCurrentTeb()->Peb;
- RtlAcquirePebLock();
+ lock_fls_section();
if (!peb->FlsCallback)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
@@ -1133,7 +1133,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
}
else SetLastError( ERROR_NO_MORE_ITEMS );
}
- RtlReleasePebLock();
+ unlock_fls_section();
return index;
}
@@ -1145,7 +1145,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index )
{
BOOL ret;
- RtlAcquirePebLock();
+ lock_fls_section();
ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
if (ret)
@@ -1155,7 +1155,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index )
if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL;
}
else SetLastError( ERROR_INVALID_PARAMETER );
- RtlReleasePebLock();
+ unlock_fls_section();
return ret;
}
--
2.25.3

View File

@ -0,0 +1,46 @@
From ee30a9aeb8db442a9cea52449959178f9d449d39 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 15:00:48 +0300
Subject: [PATCH] kernelbase: Zero all FLS slots instances in FlsFree().
---
dlls/kernelbase/thread.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 0ba67e1b6c9..9a65630cca7 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -1137,7 +1137,6 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
return index;
}
-
/***********************************************************************
* FlsFree (kernelbase.@)
*/
@@ -1148,11 +1147,17 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index )
lock_fls_section();
ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
- if (ret)
+ if (ret && NtCurrentTeb()->FlsSlots)
{
- /* FIXME: call Fls callback */
- /* FIXME: add equivalent of ThreadZeroTlsCell here */
- if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL;
+ LIST_ENTRY *entry;
+
+ for (entry = NtCurrentTeb()->Peb->FlsListHead.Flink;
+ entry != &NtCurrentTeb()->Peb->FlsListHead;
+ entry = entry->Flink)
+ {
+ /* FIXME: call Fls callback */
+ *fls_addr_from_index(entry, index) = NULL;
+ }
}
else SetLastError( ERROR_INVALID_PARAMETER );
unlock_fls_section();
--
2.25.3

View File

@ -0,0 +1,120 @@
From 7a474e95ad8cb82140e541a65b2bf338b42c3090 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 16:09:11 +0300
Subject: [PATCH] ntdll: Call FLS callbacks on thread shutdown.
---
dlls/kernel32/tests/loader.c | 26 ++++++++------------------
dlls/ntdll/loader.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 3ed3351c02e..9cddfb82d51 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -2520,18 +2520,12 @@ todo_wine
void* value;
SetLastError(0xdeadbeef);
value = pFlsGetValue(fls_index);
- todo_wine
- {
- ok(broken(value == (void*) 0x31415) || /* Win2k3 */
- value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
- }
+ ok(broken(value == (void*) 0x31415) || /* Win2k3 */
+ value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
- todo_wine
- {
- ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
- fls_callback_count == thread_detach_count + 1,
- "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
- }
+ ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
+ fls_callback_count == thread_detach_count + 1,
+ "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
}
if (pFlsFree)
{
@@ -2726,8 +2720,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++;
@@ -2757,11 +2750,8 @@ todo_wine
void* value;
SetLastError(0xdeadbeef);
value = pFlsGetValue(fls_index);
- todo_wine
- {
- ok(broken(value == (void*) 0x31415) || /* Win2k3 */
- !value, "FlsGetValue returned %p, expected NULL\n", value);
- }
+ ok(broken(value == (void*) 0x31415) || /* Win2k3 */
+ !value, "FlsGetValue returned %p, expected NULL\n", value);
ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
}
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 71ef1cfea0a..681b7f4b114 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1621,6 +1621,30 @@ static void attach_implicitly_loaded_dlls( LPVOID reserved )
}
}
+static void call_fls_callbacks(void)
+{
+ PFLS_CALLBACK_FUNCTION *fls_callbacks;
+ PRTL_BITMAP fls_bitmap;
+ void **fls_slot_data;
+ DWORD fls_index;
+
+ if ((fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback) && NtCurrentTeb()->FlsSlots)
+ {
+ fls_slot_data = (void **)((BYTE *)NtCurrentTeb()->FlsSlots + sizeof(LIST_ENTRY));
+ fls_bitmap = NtCurrentTeb()->Peb->FlsBitmap;
+ fls_index = 0;
+ for (fls_index = 0; fls_index < fls_bitmap->SizeOfBitMap; ++fls_index)
+ {
+ if (!RtlAreBitsSet( fls_bitmap, fls_index, 1 ))
+ continue;
+
+ if (fls_callbacks[fls_index + 2] && fls_slot_data[fls_index])
+ fls_callbacks[fls_index + 2](fls_slot_data[fls_index]);
+
+ fls_slot_data[fls_index] = NULL;
+ }
+ }
+}
/*************************************************************************
* process_detach
@@ -3898,6 +3922,11 @@ fail:
void WINAPI LdrShutdownProcess(void)
{
TRACE("()\n");
+
+ lock_fls_section(NULL);
+ call_fls_callbacks();
+ unlock_fls_section(NULL);
+
process_detaching = TRUE;
process_detach();
}
@@ -3936,6 +3965,7 @@ void WINAPI LdrShutdownThread(void)
{
lock_fls_section( NULL );
RemoveEntryList( (LIST_ENTRY *)NtCurrentTeb()->FlsSlots );
+ call_fls_callbacks();
unlock_fls_section( NULL );
}
--
2.25.3

View File

@ -0,0 +1,85 @@
From f675a05f09d1173308ab138ffdfcaee125c3c0ba Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 16:58:42 +0300
Subject: [PATCH] kernelbase: Call FLS callbacks from FlsFree().
---
dlls/kernel32/tests/fiber.c | 4 ++--
dlls/kernel32/tests/loader.c | 7 ++-----
dlls/kernelbase/thread.c | 13 +++++++++++--
3 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c
index 2bcc3ee60c4..3aae0400d03 100644
--- a/dlls/kernel32/tests/fiber.c
+++ b/dlls/kernel32/tests/fiber.c
@@ -344,7 +344,7 @@ static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
ret = pFlsFree( fls );
ok(ret, "FlsFree failed with error %u\n", GetLastError() );
- todo_wine ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
+ ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
/* Test that callback is not executed if value is NULL */
cbCount = 0;
@@ -416,7 +416,7 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
fls_value_to_set = val2;
pFlsFree(fls_index_to_set);
ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
- todo_wine ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
+ ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
fiberCount = 0;
cbCount = 0;
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 9cddfb82d51..21af7b4ce7a 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -2534,11 +2534,8 @@ todo_wine
ret = pFlsFree(fls_index);
ok(ret, "FlsFree failed with error %u\n", GetLastError());
fls_index = FLS_OUT_OF_INDEXES;
- todo_wine
- {
- ok(fls_callback_count == fls_count,
- "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
- }
+ ok(fls_callback_count == fls_count,
+ "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
}
ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 9a65630cca7..40ba9ea4f07 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -1149,15 +1149,24 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index )
if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
if (ret && NtCurrentTeb()->FlsSlots)
{
+ PFLS_CALLBACK_FUNCTION *fls_callbacks;
LIST_ENTRY *entry;
+ fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback;
+
for (entry = NtCurrentTeb()->Peb->FlsListHead.Flink;
entry != &NtCurrentTeb()->Peb->FlsListHead;
entry = entry->Flink)
{
- /* FIXME: call Fls callback */
- *fls_addr_from_index(entry, index) = NULL;
+ void **value_ptr = fls_addr_from_index(entry, index);
+
+ if (fls_callbacks && fls_callbacks[index + 2] && *value_ptr)
+ fls_callbacks[index + 2](*value_ptr);
+
+ *value_ptr = NULL;
}
+ if (fls_callbacks)
+ fls_callbacks[index + 2] = NULL;
}
else SetLastError( ERROR_INVALID_PARAMETER );
unlock_fls_section();
--
2.25.3

View File

@ -0,0 +1,71 @@
From 9bd8f42cf95582935440a622c76a4579ba3659f6 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Apr 2020 18:22:59 +0300
Subject: [PATCH] kernelbase: Call FLS callbacks from DeleteFiber().
---
dlls/kernel32/tests/fiber.c | 2 +-
dlls/kernelbase/thread.c | 26 +++++++++++++++++++++++++-
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c
index 3aae0400d03..b6ae9cdc2f6 100644
--- a/dlls/kernel32/tests/fiber.c
+++ b/dlls/kernel32/tests/fiber.c
@@ -409,7 +409,7 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
fls_value_to_set = val1;
pDeleteFiber(fibers[1]);
ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
- todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
+ ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
fiberCount = 0;
cbCount = 0;
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 40ba9ea4f07..09dfe162e17 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -1025,6 +1025,30 @@ LPVOID WINAPI DECLSPEC_HOTPATCH ConvertThreadToFiberEx( LPVOID param, DWORD flag
return fiber;
}
+static void call_fls_callbacks(void **fls_slots)
+{
+ PFLS_CALLBACK_FUNCTION *fls_callbacks;
+ PRTL_BITMAP fls_bitmap;
+ void **fls_slot_data;
+ DWORD fls_index;
+
+ if ((fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback))
+ {
+ fls_slot_data = (void **)((BYTE *)fls_slots + sizeof(LIST_ENTRY));
+ fls_bitmap = NtCurrentTeb()->Peb->FlsBitmap;
+ fls_index = 0;
+ for (fls_index = 0; fls_index < fls_bitmap->SizeOfBitMap; ++fls_index)
+ {
+ if (!RtlAreBitsSet( fls_bitmap, fls_index, 1 ))
+ continue;
+
+ if (fls_callbacks[fls_index + 2] && fls_slot_data[fls_index])
+ fls_callbacks[fls_index + 2](fls_slot_data[fls_index]);
+
+ fls_slot_data[fls_index] = NULL;
+ }
+ }
+}
/***********************************************************************
* DeleteFiber (kernelbase.@)
@@ -1045,8 +1069,8 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr )
{
lock_fls_section();
RemoveEntryList( (LIST_ENTRY *)fiber->fls_slots );
+ call_fls_callbacks(fiber->fls_slots);
unlock_fls_section();
-
HeapFree( GetProcessHeap(), 0, fiber->fls_slots );
}
--
2.25.3

View File

@ -0,0 +1,2 @@
Fixes: [49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called

View File

@ -176,6 +176,7 @@ patch_enable_all ()
enable_ntdll_Dealloc_Thread_Stack="$1"
enable_ntdll_DeviceType_Systemroot="$1"
enable_ntdll_Exception="$1"
enable_ntdll_FLS_Callbacks="$1"
enable_ntdll_FileDispositionInformation="$1"
enable_ntdll_FileFsFullSizeInformation="$1"
enable_ntdll_Fix_Alignment="$1"
@ -635,6 +636,9 @@ patch_enable ()
ntdll-Exception)
enable_ntdll_Exception="$2"
;;
ntdll-FLS_Callbacks)
enable_ntdll_FLS_Callbacks="$2"
;;
ntdll-FileDispositionInformation)
enable_ntdll_FileDispositionInformation="$2"
;;
@ -4521,6 +4525,32 @@ if test "$enable_ntdll_Exception" -eq 1; then
) >> "$patchlist"
fi
# Patchset ntdll-FLS_Callbacks
# |
# | This patchset fixes the following Wine bugs:
# | * [#49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called
# |
# | Modified files:
# | * dlls/kernel32/tests/fiber.c, dlls/kernel32/tests/loader.c, dlls/kernel32/tests/thread.c, dlls/kernelbase/thread.c,
# | dlls/ntdll/loader.c
# |
if test "$enable_ntdll_FLS_Callbacks" -eq 1; then
patch_apply ntdll-FLS_Callbacks/0001-kernelbase-Maintain-FLS-storage-list-in-PEB.patch
patch_apply ntdll-FLS_Callbacks/0002-kernelbase-Don-t-use-PEB-lock-for-FLS-data.patch
patch_apply ntdll-FLS_Callbacks/0003-kernelbase-Zero-all-FLS-slots-instances-in-FlsFree.patch
patch_apply ntdll-FLS_Callbacks/0004-ntdll-Call-FLS-callbacks-on-thread-shutdown.patch
patch_apply ntdll-FLS_Callbacks/0005-kernelbase-Call-FLS-callbacks-from-FlsFree.patch
patch_apply ntdll-FLS_Callbacks/0006-kernelbase-Call-FLS-callbacks-from-DeleteFiber.patch
(
printf '%s\n' '+ { "Paul Gofman", "kernelbase: Maintain FLS storage list in PEB.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "kernelbase: Don'\''t use PEB lock for FLS data.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "kernelbase: Zero all FLS slots instances in FlsFree().", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Call FLS callbacks on thread shutdown.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "kernelbase: Call FLS callbacks from FlsFree().", 1 },';
printf '%s\n' '+ { "Paul Gofman", "kernelbase: Call FLS callbacks from DeleteFiber().", 1 },';
) >> "$patchlist"
fi
# Patchset ntdll-FileFsFullSizeInformation
# |
# | Modified files: