mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added ntdll-FLS_Callbacks patchset.
This commit is contained in:
parent
4581daea3b
commit
a8b95783eb
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
2
patches/ntdll-FLS_Callbacks/definition
Normal file
2
patches/ntdll-FLS_Callbacks/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user