mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
ntdll-NtAlertThreadByThreadId: New patch set.
This commit is contained in:
parent
213037cb33
commit
dc77e28b0f
@ -1,4 +1,4 @@
|
||||
From 0cf6433af95363c5fbba2af482b2ba50b863dfb7 Mon Sep 17 00:00:00 2001
|
||||
From d02623b1c4d0fa97ea990d160529ecd98da08a85 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 2 Oct 2014 19:44:31 +0200
|
||||
Subject: [PATCH] ntdll: Print a warning message specifying the wine-staging
|
||||
@ -9,7 +9,7 @@ Subject: [PATCH] ntdll: Print a warning message specifying the wine-staging
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 20bc3f977d1..c2187a19397 100644
|
||||
index 440a77d4063..3e3acdc5eac 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -44,6 +44,7 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
@ -20,7 +20,7 @@ index 20bc3f977d1..c2187a19397 100644
|
||||
|
||||
#ifdef _WIN64
|
||||
#define DEFAULT_SECURITY_COOKIE_64 (((ULONGLONG)0x00002b99 << 32) | 0x2ddfa232)
|
||||
@@ -3456,6 +3457,7 @@ static void process_breakpoint(void)
|
||||
@@ -3509,6 +3510,7 @@ static void process_breakpoint(void)
|
||||
__ENDTRY
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ index 20bc3f977d1..c2187a19397 100644
|
||||
|
||||
/******************************************************************
|
||||
* LdrInitializeThunk (NTDLL.@)
|
||||
@@ -3465,6 +3467,9 @@ static void process_breakpoint(void)
|
||||
@@ -3518,6 +3520,9 @@ static void process_breakpoint(void)
|
||||
*/
|
||||
void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR unknown3, ULONG_PTR unknown4 )
|
||||
{
|
||||
@ -38,7 +38,7 @@ index 20bc3f977d1..c2187a19397 100644
|
||||
static int attach_done;
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
@@ -3483,6 +3488,16 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
||||
@@ -3536,6 +3541,16 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
||||
entry = (void **)&context->u.s.X0;
|
||||
#endif
|
||||
|
||||
@ -54,7 +54,7 @@ index 20bc3f977d1..c2187a19397 100644
|
||||
+
|
||||
if (process_detaching) NtTerminateThread( GetCurrentThread(), 0 );
|
||||
|
||||
RtlEnterCriticalSection( &loader_section );
|
||||
teb_list_wrlock();
|
||||
--
|
||||
2.28.0
|
||||
2.29.2
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
From ce5e1fc75139e4de9d92dfe27b4a513a96da013c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 2 Oct 2014 19:53:46 +0200
|
||||
Subject: [PATCH] winelib: Append '(Staging)' at the end of the version string.
|
||||
|
||||
---
|
||||
Makefile.in | 2 +-
|
||||
dlls/ntdll/Makefile.in | 1 +
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 307a95b3b1a..61019fed949 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -116,7 +116,7 @@ install-manpages:: manpages
|
||||
# Rules for generated source files
|
||||
|
||||
dlls/ntdll/unix/version.c: dummy
|
||||
- @version=`(GIT_DIR=$(srcdir)/.git git describe HEAD 2>/dev/null || echo "wine-$(PACKAGE_VERSION)") | sed -n -e '$$s/\(.*\)/const char wine_build[] = "\1";/p'` && (echo $$version | cmp -s - $@) || echo $$version >$@ || ($(RM) $@ && exit 1)
|
||||
+ @version=`(GIT_DIR=$(srcdir)/.git git describe HEAD 2>/dev/null || echo "wine-$(PACKAGE_VERSION)") | sed -n -e '$$s/\(.*\)/const char wine_build[] = "\1 (Staging)";/p'` && (echo $$version | cmp -s - $@) || echo $$version >$@ || (rm -f $@ && exit 1)
|
||||
|
||||
programs/winetest/build.rc: dummy
|
||||
@build="STRINGTABLE { 1 \"`GIT_DIR=$(srcdir)/.git git rev-parse HEAD 2>/dev/null`\" }" && (echo $$build | cmp -s - $@) || echo $$build >$@ || (rm -f $@ && exit 1)
|
||||
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
|
||||
index f39ffb42c6f..67847bb9392 100644
|
||||
--- a/dlls/ntdll/Makefile.in
|
||||
+++ b/dlls/ntdll/Makefile.in
|
||||
@@ -79,3 +79,4 @@ unix_loader_EXTRADEFS = \
|
||||
-DBINDIR=\"${bindir}\" \
|
||||
-DDLL_TO_BINDIR=\"`${MAKEDEP} -R ${dlldir} ${bindir}`\" \
|
||||
-DBIN_TO_DATADIR=\"`${MAKEDEP} -R ${bindir} ${datadir}/wine`\"
|
||||
+
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1 +1 @@
|
||||
#Depends: ntdll-FLS_Callbacks
|
||||
Depends: ntdll-NtAlertThreadByThreadId
|
||||
|
@ -1,4 +1,4 @@
|
||||
From ec0fc4f9f1919616dcaecd4712749761d271c7c8 Mon Sep 17 00:00:00 2001
|
||||
From b04ab24c90337271146425edc2059328e42743b6 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <zfigura@codeweavers.com>
|
||||
Date: Mon, 6 Jul 2020 17:17:31 -0500
|
||||
Subject: [PATCH] ntdll, server: Implement alertable waits.
|
||||
@ -164,29 +164,29 @@ index d1a282c65e9..2a7c3865617 100644
|
||||
|
||||
/* We need to let the server know when we are doing a message wait, and when we
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index c3ad0a41098..c2f215320ee 100644
|
||||
index 23731f0fdc6..b2020b6311a 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -57,6 +57,7 @@ struct ntdll_thread_data
|
||||
struct list entry; /* entry in TEB list */
|
||||
PRTL_THREAD_START_ROUTINE start; /* thread entry point */
|
||||
void *param; /* thread entry point parameter */
|
||||
@@ -50,6 +50,7 @@ struct ntdll_thread_data
|
||||
void *cpu_data[16]; /* reserved for CPU-specific data */
|
||||
struct debug_info *debug_info; /* info for debugstr functions */
|
||||
void *start_stack; /* stack for thread startup */
|
||||
+ int esync_apc_fd; /* fd to wait on for user APCs */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) );
|
||||
int request_fd; /* fd for sending server requests */
|
||||
int reply_fd; /* fd for receiving server replies */
|
||||
int wait_fd[2]; /* fd for sleeping server requests */
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index d79e3de662e..6b83072b750 100644
|
||||
index 785583a340a..93646bc51f4 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -2555,6 +2555,7 @@ static void init_teb( TEB *teb, PEB *peb )
|
||||
@@ -2552,6 +2552,7 @@ static void init_teb( TEB *teb, PEB *peb )
|
||||
InitializeListHead( &teb->ActivationContextStack.FrameListCache );
|
||||
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||
+ thread_data->esync_apc_fd = -1;
|
||||
thread_data->request_fd = -1;
|
||||
thread_data->reply_fd = -1;
|
||||
thread_data->wait_fd[0] = -1;
|
||||
thread_data->wait_fd[1] = -1;
|
||||
+ thread_data->esync_apc_fd = -1;
|
||||
list_add_head( &teb_list, &thread_data->entry );
|
||||
}
|
||||
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index 7b5b0761516..33a448d0a57 100644
|
||||
--- a/server/esync.c
|
||||
@ -244,10 +244,10 @@ index aeb58c5469c..cea025d9308 100644
|
||||
void esync_clear( int fd );
|
||||
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 5b8f66ffd80..a110c4c60a6 100644
|
||||
index 30296aedde8..d2772aacec2 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3714,3 +3714,7 @@ enum esync_type
|
||||
@@ -3707,3 +3707,7 @@ enum esync_type
|
||||
@REQ(esync_msgwait)
|
||||
int in_msgwait; /* are we in a message wait? */
|
||||
@END
|
||||
@ -256,7 +256,7 @@ index 5b8f66ffd80..a110c4c60a6 100644
|
||||
+@REQ(get_esync_apc_fd)
|
||||
+@END
|
||||
diff --git a/server/thread.c b/server/thread.c
|
||||
index d22555ca317..6bf4be04af5 100644
|
||||
index b52a1f5048c..6fb8684f5e0 100644
|
||||
--- a/server/thread.c
|
||||
+++ b/server/thread.c
|
||||
@@ -227,6 +227,7 @@ static inline void init_thread_structure( struct thread *thread )
|
||||
@ -267,7 +267,7 @@ index d22555ca317..6bf4be04af5 100644
|
||||
thread->debug_ctx = NULL;
|
||||
thread->system_regs = 0;
|
||||
thread->queue = NULL;
|
||||
@@ -363,7 +364,10 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
|
||||
@@ -364,7 +365,10 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
|
||||
}
|
||||
|
||||
if (do_esync())
|
||||
@ -278,7 +278,7 @@ index d22555ca317..6bf4be04af5 100644
|
||||
|
||||
set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */
|
||||
add_process_thread( thread->process, thread );
|
||||
@@ -1150,8 +1154,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
|
||||
@@ -1152,8 +1156,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
|
||||
grab_object( apc );
|
||||
list_add_tail( queue, &apc->entry );
|
||||
if (!list_prev( queue, &apc->entry )) /* first one */
|
||||
@ -292,7 +292,7 @@ index d22555ca317..6bf4be04af5 100644
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1197,6 +1206,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system
|
||||
@@ -1199,6 +1208,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system
|
||||
apc = LIST_ENTRY( ptr, struct thread_apc, entry );
|
||||
list_remove( ptr );
|
||||
}
|
||||
@ -304,7 +304,7 @@ index d22555ca317..6bf4be04af5 100644
|
||||
}
|
||||
|
||||
diff --git a/server/thread.h b/server/thread.h
|
||||
index f19080988e9..5faa2456a81 100644
|
||||
index faffe13d795..0f6108b684a 100644
|
||||
--- a/server/thread.h
|
||||
+++ b/server/thread.h
|
||||
@@ -55,6 +55,7 @@ struct thread
|
||||
@ -316,5 +316,5 @@ index f19080988e9..5faa2456a81 100644
|
||||
unsigned int system_regs; /* which system regs have been set */
|
||||
struct msg_queue *queue; /* message queue */
|
||||
--
|
||||
2.28.0
|
||||
2.29.2
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
Fixes: Do not allow to deallocate thread stack for current thread
|
||||
Depends: ntdll-NtAlertThreadByThreadId
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,241 @@
|
||||
From 2107fb9f59bb2beef3b8c12a2adf9cb2be469036 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 9 Jan 2020 14:51:05 -0600
|
||||
Subject: [PATCH 02/13] ntdll/tests: Add some tests for Rtl* resources.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/sync.c | 202 ++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 183 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
|
||||
index 9967a2be257..152cdd1530d 100644
|
||||
--- a/dlls/ntdll/tests/sync.c
|
||||
+++ b/dlls/ntdll/tests/sync.c
|
||||
@@ -41,7 +41,12 @@ static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * );
|
||||
static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * );
|
||||
static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * );
|
||||
static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
|
||||
+static BOOLEAN (WINAPI *pRtlAcquireResourceExclusive)( RTL_RWLOCK *, BOOLEAN );
|
||||
+static BOOLEAN (WINAPI *pRtlAcquireResourceShared)( RTL_RWLOCK *, BOOLEAN );
|
||||
+static void (WINAPI *pRtlDeleteResource)( RTL_RWLOCK * );
|
||||
+static void (WINAPI *pRtlInitializeResource)( RTL_RWLOCK * );
|
||||
static void (WINAPI *pRtlInitUnicodeString)( UNICODE_STRING *, const WCHAR * );
|
||||
+static void (WINAPI *pRtlReleaseResource)( RTL_RWLOCK * );
|
||||
static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
|
||||
static void (WINAPI *pRtlWakeAddressAll)( const void * );
|
||||
static void (WINAPI *pRtlWakeAddressSingle)( const void * );
|
||||
@@ -496,32 +501,191 @@ static void test_wait_on_address(void)
|
||||
ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
|
||||
}
|
||||
|
||||
+HANDLE thread_ready, thread_done;
|
||||
+
|
||||
+static DWORD WINAPI resource_shared_thread(void *arg)
|
||||
+{
|
||||
+ RTL_RWLOCK *resource = arg;
|
||||
+ BOOLEAN ret;
|
||||
+
|
||||
+ ret = pRtlAcquireResourceShared(resource, TRUE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+
|
||||
+ SetEvent(thread_ready);
|
||||
+ ok(!WaitForSingleObject(thread_done, 1000), "wait failed\n");
|
||||
+ pRtlReleaseResource(resource);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static DWORD WINAPI resource_exclusive_thread(void *arg)
|
||||
+{
|
||||
+ RTL_RWLOCK *resource = arg;
|
||||
+ BOOLEAN ret;
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(resource, TRUE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+
|
||||
+ SetEvent(thread_ready);
|
||||
+ ok(!WaitForSingleObject(thread_done, 1000), "wait failed\n");
|
||||
+ pRtlReleaseResource(resource);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void test_resource(void)
|
||||
+{
|
||||
+ HANDLE thread, thread2;
|
||||
+ RTL_RWLOCK resource;
|
||||
+ BOOLEAN ret;
|
||||
+
|
||||
+ pRtlInitializeResource(&resource);
|
||||
+ thread_ready = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
+ thread_done = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
+
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == FALSE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */
|
||||
+
|
||||
+ thread = CreateThread(NULL, 0, resource_shared_thread, &resource, 0, NULL);
|
||||
+ ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == FALSE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ SetEvent(thread_done);
|
||||
+ ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
|
||||
+ CloseHandle(thread);
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ /* Acquire the resource as exclusive, and then spawn a shared thread. */
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ thread = CreateThread(NULL, 0, resource_shared_thread, &resource, 0, NULL);
|
||||
+ ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
|
||||
+ SetEvent(thread_done);
|
||||
+ ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
|
||||
+ CloseHandle(thread);
|
||||
+
|
||||
+ /* Acquire the resource as shared, and then spawn an exclusive thread. */
|
||||
+
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ thread = CreateThread(NULL, 0, resource_exclusive_thread, &resource, 0, NULL);
|
||||
+ ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == FALSE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
|
||||
+ SetEvent(thread_done);
|
||||
+ ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
|
||||
+ CloseHandle(thread);
|
||||
+
|
||||
+ /* Spawn a shared and then exclusive waiter. */
|
||||
+ thread = CreateThread(NULL, 0, resource_shared_thread, &resource, 0, NULL);
|
||||
+ ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
|
||||
+ thread2 = CreateThread(NULL, 0, resource_exclusive_thread, &resource, 0, NULL);
|
||||
+ ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == FALSE, "got %u\n", ret);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ SetEvent(thread_done);
|
||||
+ ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
|
||||
+ CloseHandle(thread);
|
||||
+
|
||||
+ ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
|
||||
+ SetEvent(thread_done);
|
||||
+ ok(!WaitForSingleObject(thread2, 1000), "wait failed\n");
|
||||
+ CloseHandle(thread2);
|
||||
+
|
||||
+ ret = pRtlAcquireResourceExclusive(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+ ret = pRtlAcquireResourceShared(&resource, FALSE);
|
||||
+ ok(ret == TRUE, "got %u\n", ret);
|
||||
+ pRtlReleaseResource(&resource);
|
||||
+
|
||||
+ CloseHandle(thread_ready);
|
||||
+ CloseHandle(thread_done);
|
||||
+ pRtlDeleteResource(&resource);
|
||||
+}
|
||||
+
|
||||
START_TEST(sync)
|
||||
{
|
||||
HMODULE module = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
- pNtClose = (void *)GetProcAddress(module, "NtClose");
|
||||
- pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent");
|
||||
- pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
|
||||
- pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant");
|
||||
- pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent");
|
||||
- pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent");
|
||||
- pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent");
|
||||
- pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent");
|
||||
- pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant");
|
||||
- pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime");
|
||||
- pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent");
|
||||
- pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant");
|
||||
- pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent");
|
||||
- pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent");
|
||||
- pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
|
||||
- pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString");
|
||||
- pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress");
|
||||
- pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll");
|
||||
- pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle");
|
||||
+ pNtClose = (void *)GetProcAddress(module, "NtClose");
|
||||
+ pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent");
|
||||
+ pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
|
||||
+ pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant");
|
||||
+ pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent");
|
||||
+ pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent");
|
||||
+ pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent");
|
||||
+ pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent");
|
||||
+ pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant");
|
||||
+ pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime");
|
||||
+ pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent");
|
||||
+ pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant");
|
||||
+ pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent");
|
||||
+ pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent");
|
||||
+ pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
|
||||
+ pRtlAcquireResourceExclusive = (void *)GetProcAddress(module, "RtlAcquireResourceExclusive");
|
||||
+ pRtlAcquireResourceShared = (void *)GetProcAddress(module, "RtlAcquireResourceShared");
|
||||
+ pRtlDeleteResource = (void *)GetProcAddress(module, "RtlDeleteResource");
|
||||
+ pRtlInitializeResource = (void *)GetProcAddress(module, "RtlInitializeResource");
|
||||
+ pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString");
|
||||
+ pRtlReleaseResource = (void *)GetProcAddress(module, "RtlReleaseResource");
|
||||
+ pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress");
|
||||
+ pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll");
|
||||
+ pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle");
|
||||
|
||||
test_wait_on_address();
|
||||
test_event();
|
||||
test_mutant();
|
||||
test_keyed_events();
|
||||
+ test_resource();
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,81 @@
|
||||
From 0fdd0e4d59af06ed8b225e87802001ab53cb4906 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 22:56:03 -0500
|
||||
Subject: [PATCH 03/13] ntdll: Use a separate mutex to lock the TEB list.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 785583a340a..2e5e94f80f8 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -163,6 +163,7 @@ static void *teb_block;
|
||||
static void **next_free_teb;
|
||||
static int teb_block_pos;
|
||||
static struct list teb_list = LIST_INIT( teb_list );
|
||||
+static pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
#define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask)))
|
||||
#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
|
||||
@@ -2556,7 +2557,9 @@ static void init_teb( TEB *teb, PEB *peb )
|
||||
thread_data->reply_fd = -1;
|
||||
thread_data->wait_fd[0] = -1;
|
||||
thread_data->wait_fd[1] = -1;
|
||||
+ pthread_rwlock_wrlock( &teb_list_lock );
|
||||
list_add_head( &teb_list, &thread_data->entry );
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
}
|
||||
|
||||
|
||||
@@ -2678,7 +2681,9 @@ void virtual_free_teb( TEB *teb )
|
||||
}
|
||||
|
||||
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
|
||||
+ pthread_rwlock_wrlock( &teb_list_lock );
|
||||
list_remove( &thread_data->entry );
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
ptr = (char *)teb - teb_offset;
|
||||
*(void **)ptr = next_free_teb;
|
||||
next_free_teb = ptr;
|
||||
@@ -2692,17 +2697,16 @@ void virtual_free_teb( TEB *teb )
|
||||
NTSTATUS virtual_clear_tls_index( ULONG index )
|
||||
{
|
||||
struct ntdll_thread_data *thread_data;
|
||||
- sigset_t sigset;
|
||||
|
||||
if (index < TLS_MINIMUM_AVAILABLE)
|
||||
{
|
||||
- server_enter_uninterrupted_section( &virtual_mutex, &sigset );
|
||||
+ pthread_rwlock_rdlock( &teb_list_lock );
|
||||
LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry )
|
||||
{
|
||||
TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch );
|
||||
teb->TlsSlots[index] = 0;
|
||||
}
|
||||
- server_leave_uninterrupted_section( &virtual_mutex, &sigset );
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2710,13 +2714,13 @@ NTSTATUS virtual_clear_tls_index( ULONG index )
|
||||
if (index >= 8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
- server_enter_uninterrupted_section( &virtual_mutex, &sigset );
|
||||
+ pthread_rwlock_rdlock( &teb_list_lock );
|
||||
LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry )
|
||||
{
|
||||
TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch );
|
||||
if (teb->TlsExpansionSlots) teb->TlsExpansionSlots[index] = 0;
|
||||
}
|
||||
- server_leave_uninterrupted_section( &virtual_mutex, &sigset );
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,172 @@
|
||||
From 3606a80ff21447e459950899b409416873722031 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:00:16 -0500
|
||||
Subject: [PATCH 04/13] ntdll: Implement NtAlertThreadByThreadId() and
|
||||
NtWaitForAlertByThreadId().
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/ntdll.spec | 2 ++
|
||||
dlls/ntdll/unix/sync.c | 45 ++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/thread.c | 2 ++
|
||||
dlls/ntdll/unix/unix_private.h | 3 +++
|
||||
dlls/ntdll/unix/virtual.c | 5 ++--
|
||||
include/winternl.h | 2 ++
|
||||
6 files changed, 57 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
|
||||
index f5ac924a945..c63b7a3e5fe 100644
|
||||
--- a/dlls/ntdll/ntdll.spec
|
||||
+++ b/dlls/ntdll/ntdll.spec
|
||||
@@ -137,6 +137,7 @@
|
||||
@ stdcall -syscall NtAdjustPrivilegesToken(long long ptr long ptr ptr)
|
||||
@ stdcall -syscall NtAlertResumeThread(long ptr)
|
||||
@ stdcall -syscall NtAlertThread(long)
|
||||
+@ stdcall -syscall NtAlertThreadByThreadId(ptr)
|
||||
@ stdcall -syscall NtAllocateLocallyUniqueId(ptr)
|
||||
# @ stub NtAllocateUserPhysicalPages
|
||||
@ stdcall -syscall NtAllocateUuids(ptr ptr ptr ptr)
|
||||
@@ -422,6 +423,7 @@
|
||||
@ stdcall -syscall NtUnmapViewOfSection(long ptr)
|
||||
@ stub NtVdmControl
|
||||
@ stub NtW32Call
|
||||
+@ stdcall -syscall NtWaitForAlertByThreadId(ptr ptr)
|
||||
# @ stub NtWaitForDebugEvent
|
||||
@ stdcall -syscall NtWaitForKeyedEvent(long ptr long ptr)
|
||||
@ stdcall -syscall NtWaitForMultipleObjects(long ptr long long ptr)
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index dcc8c5447ef..2ed164368b9 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -81,6 +81,12 @@ static const LARGE_INTEGER zero_timeout;
|
||||
|
||||
static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
+static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
|
||||
+{
|
||||
+ if (!timeout) return "(infinite)";
|
||||
+ return wine_dbgstr_longlong( timeout->QuadPart );
|
||||
+}
|
||||
+
|
||||
/* return a monotonic time counter, in Win32 ticks */
|
||||
static inline ULONGLONG monotonic_counter(void)
|
||||
{
|
||||
@@ -2119,6 +2125,45 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
||||
}
|
||||
|
||||
|
||||
+/***********************************************************************
|
||||
+ * NtAlertThreadByThreadId (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||
+{
|
||||
+ struct ntdll_thread_data *thread_data;
|
||||
+
|
||||
+ TRACE( "%p\n", tid );
|
||||
+
|
||||
+ pthread_rwlock_rdlock( &teb_list_lock );
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry )
|
||||
+ {
|
||||
+ TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch );
|
||||
+
|
||||
+ if (teb->ClientId.UniqueThread == tid)
|
||||
+ {
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
+ NtSetEvent( thread_data->tid_alert_event, NULL );
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pthread_rwlock_unlock( &teb_list_lock );
|
||||
+ return STATUS_INVALID_CID;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * NtWaitForAlertByThreadId (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout )
|
||||
+{
|
||||
+ TRACE( "%p %s\n", address, debugstr_timeout( timeout ) );
|
||||
+
|
||||
+ return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout );
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifdef __linux__
|
||||
|
||||
NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
|
||||
index 9808fc610e3..bb55b3d29ed 100644
|
||||
--- a/dlls/ntdll/unix/thread.c
|
||||
+++ b/dlls/ntdll/unix/thread.c
|
||||
@@ -252,6 +252,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
|
||||
thread_data->start = start;
|
||||
thread_data->param = param;
|
||||
|
||||
+ NtCreateEvent( &thread_data->tid_alert_event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE );
|
||||
+
|
||||
pthread_attr_init( &pthread_attr );
|
||||
pthread_attr_setstack( &pthread_attr, teb->DeallocationStack,
|
||||
(char *)teb->Tib.StackBase + extra_stack - (char *)teb->DeallocationStack );
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 23731f0fdc6..9ae7cba34a7 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -57,6 +57,7 @@ struct ntdll_thread_data
|
||||
struct list entry; /* entry in TEB list */
|
||||
PRTL_THREAD_START_ROUTINE start; /* thread entry point */
|
||||
void *param; /* thread entry point parameter */
|
||||
+ HANDLE tid_alert_event; /* event for thread-id alerts */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) );
|
||||
@@ -113,6 +114,8 @@ extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT
|
||||
|
||||
extern void CDECL set_show_dot_files( BOOL enable ) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern struct list teb_list DECLSPEC_HIDDEN;
|
||||
+extern pthread_rwlock_t teb_list_lock DECLSPEC_HIDDEN;
|
||||
extern const char *home_dir DECLSPEC_HIDDEN;
|
||||
extern const char *data_dir DECLSPEC_HIDDEN;
|
||||
extern const char *build_dir DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 2e5e94f80f8..96650e064c3 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -162,8 +162,9 @@ struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
|
||||
static void *teb_block;
|
||||
static void **next_free_teb;
|
||||
static int teb_block_pos;
|
||||
-static struct list teb_list = LIST_INIT( teb_list );
|
||||
-static pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
+
|
||||
+struct list teb_list = LIST_INIT( teb_list );
|
||||
+pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
#define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask)))
|
||||
#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index a7b0e04aade..b155b4e39b2 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -3040,6 +3040,7 @@ NTSYSAPI NTSTATUS WINAPI NtAdjustGroupsToken(HANDLE,BOOLEAN,PTOKEN_GROUPS,ULONG
|
||||
NTSYSAPI NTSTATUS WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
|
||||
NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle);
|
||||
+NTSYSAPI NTSTATUS WINAPI NtAlertThreadByThreadId(HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid);
|
||||
NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR);
|
||||
NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG_PTR,SIZE_T*,ULONG,ULONG);
|
||||
@@ -3272,6 +3273,7 @@ NTSYSAPI NTSTATUS WINAPI NtUnlockFile(HANDLE,PIO_STATUS_BLOCK,PLARGE_INTEGER,PL
|
||||
NTSYSAPI NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
|
||||
NTSYSAPI NTSTATUS WINAPI NtVdmControl(ULONG,PVOID);
|
||||
+NTSYSAPI NTSTATUS WINAPI NtWaitForAlertByThreadId(const void*,const LARGE_INTEGER*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE,const void*,BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,114 @@
|
||||
From 03fe17e93090c3cc3b9cbc9f92bc48ff39d84a07 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:01:25 -0500
|
||||
Subject: [PATCH 05/13] ntdll/tests: Add basic tests for thread-id alert
|
||||
functions.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/sync.c | 59 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 59 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
|
||||
index 152cdd1530d..a6631dd40a9 100644
|
||||
--- a/dlls/ntdll/tests/sync.c
|
||||
+++ b/dlls/ntdll/tests/sync.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "winternl.h"
|
||||
#include "wine/test.h"
|
||||
|
||||
+static NTSTATUS (WINAPI *pNtAlertThreadByThreadId)( HANDLE );
|
||||
static NTSTATUS (WINAPI *pNtClose)( HANDLE );
|
||||
static NTSTATUS (WINAPI *pNtCreateEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, BOOLEAN, BOOLEAN );
|
||||
static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
|
||||
@@ -40,6 +41,7 @@ static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, c
|
||||
static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * );
|
||||
static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * );
|
||||
static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * );
|
||||
+static NTSTATUS (WINAPI *pNtWaitForAlertByThreadId)( void *, const LARGE_INTEGER * );
|
||||
static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
|
||||
static BOOLEAN (WINAPI *pRtlAcquireResourceExclusive)( RTL_RWLOCK *, BOOLEAN );
|
||||
static BOOLEAN (WINAPI *pRtlAcquireResourceShared)( RTL_RWLOCK *, BOOLEAN );
|
||||
@@ -654,10 +656,65 @@ static void test_resource(void)
|
||||
pRtlDeleteResource(&resource);
|
||||
}
|
||||
|
||||
+static void test_thread_id_alert( char **argv )
|
||||
+{
|
||||
+ static const LARGE_INTEGER zero;
|
||||
+ char cmdline[MAX_PATH];
|
||||
+ STARTUPINFOA si = {0};
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ NTSTATUS ret;
|
||||
+
|
||||
+ if (!pNtWaitForAlertByThreadId)
|
||||
+ {
|
||||
+ win_skip("NtWaitForAlertByThreadId is not available\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero );
|
||||
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtAlertThreadByThreadId( 0 );
|
||||
+ ok(ret == STATUS_INVALID_CID, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtAlertThreadByThreadId( (HANDLE)0xdeadbeef );
|
||||
+ ok(ret == STATUS_INVALID_CID, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)GetCurrentThreadId() );
|
||||
+ ok(!ret, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)GetCurrentThreadId() );
|
||||
+ ok(!ret, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero );
|
||||
+ ok(ret == STATUS_ALERTED, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero );
|
||||
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||||
+
|
||||
+ ret = pNtWaitForAlertByThreadId( (void *)0x321, &zero );
|
||||
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||||
+
|
||||
+ sprintf( cmdline, "%s %s subprocess", argv[0], argv[1] );
|
||||
+ ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
|
||||
+ ok(ret, "failed to create process, error %u\n", GetLastError());
|
||||
+ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)pi.dwThreadId );
|
||||
+ todo_wine ok(ret == STATUS_ACCESS_DENIED, "got %#x\n", ret);
|
||||
+ ok(!WaitForSingleObject( pi.hProcess, 1000 ), "wait failed\n");
|
||||
+ CloseHandle( pi.hProcess );
|
||||
+ CloseHandle( pi.hThread );
|
||||
+}
|
||||
+
|
||||
START_TEST(sync)
|
||||
{
|
||||
HMODULE module = GetModuleHandleA("ntdll.dll");
|
||||
+ char **argv;
|
||||
+ int argc;
|
||||
+
|
||||
+ argc = winetest_get_mainargs( &argv );
|
||||
+
|
||||
+ if (argc > 2) return;
|
||||
|
||||
+ pNtAlertThreadByThreadId = (void *)GetProcAddress(module, "NtAlertThreadByThreadId");
|
||||
pNtClose = (void *)GetProcAddress(module, "NtClose");
|
||||
pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent");
|
||||
pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
|
||||
@@ -672,6 +729,7 @@ START_TEST(sync)
|
||||
pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant");
|
||||
pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent");
|
||||
pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent");
|
||||
+ pNtWaitForAlertByThreadId = (void *)GetProcAddress(module, "NtWaitForAlertByThreadId");
|
||||
pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
|
||||
pRtlAcquireResourceExclusive = (void *)GetProcAddress(module, "RtlAcquireResourceExclusive");
|
||||
pRtlAcquireResourceShared = (void *)GetProcAddress(module, "RtlAcquireResourceShared");
|
||||
@@ -688,4 +746,5 @@ START_TEST(sync)
|
||||
test_mutant();
|
||||
test_keyed_events();
|
||||
test_resource();
|
||||
+ test_thread_id_alert( argv );
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,119 @@
|
||||
From c6423d645d002113fce7b3194023ec507549c39a Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:02:56 -0500
|
||||
Subject: [PATCH 06/13] ntdll: Implement thread-id alerts on top of futexes if
|
||||
possible.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/sync.c | 65 ++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/unix_private.h | 3 ++
|
||||
2 files changed, 68 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index 2ed164368b9..3fd3545bbbb 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -2143,6 +2143,15 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||
if (teb->ClientId.UniqueThread == tid)
|
||||
{
|
||||
pthread_rwlock_unlock( &teb_list_lock );
|
||||
+#ifdef __linux__
|
||||
+ if (use_futexes())
|
||||
+ {
|
||||
+ int *futex = &thread_data->tid_alert_futex;
|
||||
+ if (!InterlockedExchange( futex, 1 ))
|
||||
+ futex_wake( futex, 1 );
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+#endif
|
||||
NtSetEvent( thread_data->tid_alert_event, NULL );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2153,6 +2162,28 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||
}
|
||||
|
||||
|
||||
+static LONGLONG get_absolute_timeout( const LARGE_INTEGER *timeout )
|
||||
+{
|
||||
+ LARGE_INTEGER now;
|
||||
+
|
||||
+ if (timeout->QuadPart >= 0) return timeout->QuadPart;
|
||||
+ NtQuerySystemTime( &now );
|
||||
+ return now.QuadPart - timeout->QuadPart;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static LONGLONG update_timeout( ULONGLONG end )
|
||||
+{
|
||||
+ LARGE_INTEGER now;
|
||||
+ LONGLONG timeleft;
|
||||
+
|
||||
+ NtQuerySystemTime( &now );
|
||||
+ timeleft = end - now.QuadPart;
|
||||
+ if (timeleft < 0) timeleft = 0;
|
||||
+ return timeleft;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/***********************************************************************
|
||||
* NtWaitForAlertByThreadId (NTDLL.@)
|
||||
*/
|
||||
@@ -2160,6 +2191,40 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||
{
|
||||
TRACE( "%p %s\n", address, debugstr_timeout( timeout ) );
|
||||
|
||||
+#ifdef __linux__
|
||||
+ if (use_futexes())
|
||||
+ {
|
||||
+ int *futex = &ntdll_get_thread_data()->tid_alert_futex;
|
||||
+ ULONGLONG end;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (timeout)
|
||||
+ {
|
||||
+ if (timeout->QuadPart == TIMEOUT_INFINITE)
|
||||
+ timeout = NULL;
|
||||
+ else
|
||||
+ end = get_absolute_timeout( timeout );
|
||||
+ }
|
||||
+
|
||||
+ while (!InterlockedExchange( futex, 0 ))
|
||||
+ {
|
||||
+ if (timeout)
|
||||
+ {
|
||||
+ LONGLONG timeleft = update_timeout( end );
|
||||
+ struct timespec timespec;
|
||||
+
|
||||
+ timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
|
||||
+ timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100;
|
||||
+ ret = futex_wait( futex, 0, ×pec );
|
||||
+ }
|
||||
+ else
|
||||
+ ret = futex_wait( futex, 0, NULL );
|
||||
+
|
||||
+ if (ret == -1 && errno == ETIMEDOUT) return STATUS_TIMEOUT;
|
||||
+ }
|
||||
+ return STATUS_ALERTED;
|
||||
+ }
|
||||
+#endif
|
||||
return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout );
|
||||
}
|
||||
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 9ae7cba34a7..327e12519a0 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -57,6 +57,9 @@ struct ntdll_thread_data
|
||||
struct list entry; /* entry in TEB list */
|
||||
PRTL_THREAD_START_ROUTINE start; /* thread entry point */
|
||||
void *param; /* thread entry point parameter */
|
||||
+#ifdef __linux__
|
||||
+ int tid_alert_futex; /* futex for thread-id alerts */
|
||||
+#endif
|
||||
HANDLE tid_alert_event; /* event for thread-id alerts */
|
||||
};
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,127 @@
|
||||
From b281eaa388b6dc0c0c539cc76236a0529668fcff Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:03:34 -0500
|
||||
Subject: [PATCH 07/13] ntdll: Implement thread-id alerts on top of Mach
|
||||
semaphores on Mac.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/sync.c | 44 ++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/thread.c | 4 ++++
|
||||
dlls/ntdll/unix/unix_private.h | 4 ++++
|
||||
3 files changed, 52 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index 3fd3545bbbb..e4aa03f94da 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -2143,6 +2143,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||
if (teb->ClientId.UniqueThread == tid)
|
||||
{
|
||||
pthread_rwlock_unlock( &teb_list_lock );
|
||||
+#ifdef __APPLE__
|
||||
+ semaphore_signal( &thread_data->tid_alert_sem );
|
||||
+ return STATUS_SUCCESS;
|
||||
+#else
|
||||
#ifdef __linux__
|
||||
if (use_futexes())
|
||||
{
|
||||
@@ -2154,6 +2158,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||
#endif
|
||||
NtSetEvent( thread_data->tid_alert_event, NULL );
|
||||
return STATUS_SUCCESS;
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2191,6 +2196,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||
{
|
||||
TRACE( "%p %s\n", address, debugstr_timeout( timeout ) );
|
||||
|
||||
+#ifdef __APPLE__
|
||||
+ {
|
||||
+ semaphore_t sem = ntdll_get_thread_data()->tid_alert_sem;
|
||||
+ ULONGLONG end;
|
||||
+ kern_return_t ret;
|
||||
+
|
||||
+ if (timeout)
|
||||
+ {
|
||||
+ if (timeout->QuadPart == TIMEOUT_INFINITE)
|
||||
+ timeout = NULL;
|
||||
+ else
|
||||
+ end = get_absolute_timeout( timeout );
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ if (timeout)
|
||||
+ {
|
||||
+ LONGLONG timeleft = update_timeout( end );
|
||||
+ mach_timespec_t timespec;
|
||||
+
|
||||
+ timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
|
||||
+ timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100;
|
||||
+ ret = semaphore_timedwait( sem, ×pec );
|
||||
+ }
|
||||
+ else
|
||||
+ ret = semaphore_wait( sem );
|
||||
+
|
||||
+ switch (ret)
|
||||
+ {
|
||||
+ case KERN_SUCCESS: return STATUS_ALERTED;
|
||||
+ case KERN_ABORTED: continue;
|
||||
+ case KERN_OPERATION_TIMED_OUT: return STATUS_TIMEOUT;
|
||||
+ default: return STATUS_INVALID_HANDLE;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#else
|
||||
#ifdef __linux__
|
||||
if (use_futexes())
|
||||
{
|
||||
@@ -2226,6 +2269,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||
}
|
||||
#endif
|
||||
return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout );
|
||||
+#endif
|
||||
}
|
||||
|
||||
|
||||
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
|
||||
index bb55b3d29ed..05157e24ace 100644
|
||||
--- a/dlls/ntdll/unix/thread.c
|
||||
+++ b/dlls/ntdll/unix/thread.c
|
||||
@@ -252,7 +252,11 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
|
||||
thread_data->start = start;
|
||||
thread_data->param = param;
|
||||
|
||||
+#ifdef __APPLE__
|
||||
+ semaphore_create( mach_task_self(), &thread_data->tid_alert_sem, SYNC_POLICY_FIFO, 0 );
|
||||
+#else
|
||||
NtCreateEvent( &thread_data->tid_alert_event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE );
|
||||
+#endif
|
||||
|
||||
pthread_attr_init( &pthread_attr );
|
||||
pthread_attr_setstack( &pthread_attr, teb->DeallocationStack,
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 327e12519a0..9e94c0ec13c 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -57,10 +57,14 @@ struct ntdll_thread_data
|
||||
struct list entry; /* entry in TEB list */
|
||||
PRTL_THREAD_START_ROUTINE start; /* thread entry point */
|
||||
void *param; /* thread entry point parameter */
|
||||
+#ifdef __APPLE__
|
||||
+ semaphore_t tid_alert_sem; /* Mach semaphore for thread-id alerts */
|
||||
+#else
|
||||
#ifdef __linux__
|
||||
int tid_alert_futex; /* futex for thread-id alerts */
|
||||
#endif
|
||||
HANDLE tid_alert_event; /* event for thread-id alerts */
|
||||
+#endif
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) );
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,156 @@
|
||||
From a9f438755a74e85cfb3b9dd122058c722ffa2f3c Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Wed, 28 Oct 2020 17:31:00 -0500
|
||||
Subject: [PATCH 08/13] ntdll: Use a separate lock to access the PE TEB list.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/loader.c | 70 +++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 64 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 45ad496fd64..26443a8c4f4 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -127,7 +127,6 @@ typedef struct _wine_modref
|
||||
|
||||
static UINT tls_module_count; /* number of modules with TLS directory */
|
||||
static IMAGE_TLS_DIRECTORY *tls_dirs; /* array of TLS directories */
|
||||
-LIST_ENTRY tls_links = { &tls_links, &tls_links };
|
||||
|
||||
static RTL_CRITICAL_SECTION loader_section;
|
||||
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
@@ -184,6 +183,55 @@ static inline BOOL contains_path( LPCWSTR name )
|
||||
return ((*name && (name[1] == ':')) || wcschr(name, '/') || wcschr(name, '\\'));
|
||||
}
|
||||
|
||||
+/* We need to access this lock from inside the implementation of (process-local)
|
||||
+ * synchronization functions, which makes actually scheduling more than a little
|
||||
+ * difficult.
|
||||
+ *
|
||||
+ * On the other hand, we want to make this a read/write lock, not just to avoid
|
||||
+ * lock contention, but also because lock contention is particularly expensive
|
||||
+ * for a spinlock.
|
||||
+ */
|
||||
+LIST_ENTRY tls_links = { &tls_links, &tls_links };
|
||||
+static LONG teb_spinlock;
|
||||
+
|
||||
+#define TEB_SPINLOCK_WRITE (-1)
|
||||
+
|
||||
+static inline void small_pause(void)
|
||||
+{
|
||||
+#ifdef __i386__
|
||||
+ __asm__ __volatile__( "rep;nop" : : : "memory" );
|
||||
+#else
|
||||
+ __asm__ __volatile__( "" : : : "memory" );
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void teb_list_rdlock(void)
|
||||
+{
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ LONG old = teb_spinlock;
|
||||
+ if (old != TEB_SPINLOCK_WRITE && InterlockedCompareExchange( &teb_spinlock, old + 1, old ) == old)
|
||||
+ return;
|
||||
+ small_pause();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void teb_list_rdunlock(void)
|
||||
+{
|
||||
+ InterlockedDecrement( &teb_spinlock );
|
||||
+}
|
||||
+
|
||||
+static void teb_list_wrlock(void)
|
||||
+{
|
||||
+ while (InterlockedCompareExchange( &teb_spinlock, TEB_SPINLOCK_WRITE, 0 ))
|
||||
+ small_pause();
|
||||
+}
|
||||
+
|
||||
+static void teb_list_wrunlock(void)
|
||||
+{
|
||||
+ InterlockedExchange( &teb_spinlock, 0 );
|
||||
+}
|
||||
+
|
||||
#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
|
||||
|
||||
typedef struct _RTL_UNLOAD_EVENT_TRACE
|
||||
@@ -991,13 +1039,18 @@ static SHORT alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod )
|
||||
if (!new_ptr) return -1;
|
||||
|
||||
/* resize the pointer block in all running threads */
|
||||
+ teb_list_rdlock();
|
||||
for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
|
||||
{
|
||||
TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
|
||||
void **old = teb->ThreadLocalStoragePointer;
|
||||
void **new = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new));
|
||||
|
||||
- if (!new) return -1;
|
||||
+ if (!new)
|
||||
+ {
|
||||
+ teb_list_rdunlock();
|
||||
+ return -1;
|
||||
+ }
|
||||
if (old) memcpy( new, old, tls_module_count * sizeof(*new) );
|
||||
teb->ThreadLocalStoragePointer = new;
|
||||
#ifdef __x86_64__ /* macOS-specific hack */
|
||||
@@ -1006,12 +1059,14 @@ static SHORT alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod )
|
||||
TRACE( "thread %04lx tls block %p -> %p\n", (ULONG_PTR)teb->ClientId.UniqueThread, old, new );
|
||||
/* FIXME: can't free old block here, should be freed at thread exit */
|
||||
}
|
||||
+ teb_list_rdunlock();
|
||||
|
||||
tls_dirs = new_ptr;
|
||||
tls_module_count = new_count;
|
||||
}
|
||||
|
||||
/* allocate the data block in all running threads */
|
||||
+ teb_list_rdlock();
|
||||
for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
|
||||
{
|
||||
TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
|
||||
@@ -1026,6 +1081,7 @@ static SHORT alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod )
|
||||
RtlFreeHeap( GetProcessHeap(), 0,
|
||||
InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr ));
|
||||
}
|
||||
+ teb_list_rdunlock();
|
||||
|
||||
*(DWORD *)dir->AddressOfIndex = i;
|
||||
tls_dirs[i] = *dir;
|
||||
@@ -3243,7 +3299,9 @@ void WINAPI LdrShutdownThread(void)
|
||||
if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.DllBase, DLL_THREAD_DETACH );
|
||||
|
||||
RtlAcquirePebLock();
|
||||
+ teb_list_wrlock();
|
||||
RemoveEntryList( &NtCurrentTeb()->TlsLinks );
|
||||
+ teb_list_wrunlock();
|
||||
if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer))
|
||||
{
|
||||
for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] );
|
||||
@@ -3480,6 +3538,10 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
||||
|
||||
if (process_detaching) NtTerminateThread( GetCurrentThread(), 0 );
|
||||
|
||||
+ teb_list_wrlock();
|
||||
+ InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
|
||||
+ teb_list_wrunlock();
|
||||
+
|
||||
RtlEnterCriticalSection( &loader_section );
|
||||
|
||||
wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||
@@ -3502,10 +3564,6 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
||||
imports_fixup_done = TRUE;
|
||||
}
|
||||
|
||||
- RtlAcquirePebLock();
|
||||
- InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
|
||||
- RtlReleasePebLock();
|
||||
-
|
||||
NtCurrentTeb()->FlsSlots = fls_alloc_data();
|
||||
|
||||
if (!attach_done) /* first time around */
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,397 @@
|
||||
From e27be2eef2738f6c7f213d70ee5554b052d07ec1 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 2 Nov 2020 20:24:07 -0600
|
||||
Subject: [PATCH 09/13] ntdll: Reimplement Win32 futexes on top of thread-ID
|
||||
alerts.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/loader.c | 4 +-
|
||||
dlls/ntdll/ntdll_misc.h | 2 +
|
||||
dlls/ntdll/sync.c | 77 ++++++++++++++++++-
|
||||
dlls/ntdll/unix/loader.c | 3 -
|
||||
dlls/ntdll/unix/sync.c | 162 ---------------------------------------
|
||||
dlls/ntdll/unixlib.h | 6 +-
|
||||
6 files changed, 79 insertions(+), 175 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 26443a8c4f4..440a77d4063 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -205,7 +205,7 @@ static inline void small_pause(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
-static void teb_list_rdlock(void)
|
||||
+void teb_list_rdlock(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -216,7 +216,7 @@ static void teb_list_rdlock(void)
|
||||
}
|
||||
}
|
||||
|
||||
-static void teb_list_rdunlock(void)
|
||||
+void teb_list_rdunlock(void)
|
||||
{
|
||||
InterlockedDecrement( &teb_spinlock );
|
||||
}
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 41e8666a25c..6a46946b218 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -71,6 +71,8 @@ extern BOOL is_wow64 DECLSPEC_HIDDEN;
|
||||
|
||||
/* module handling */
|
||||
extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
|
||||
+extern void teb_list_rdlock(void) DECLSPEC_HIDDEN;
|
||||
+extern void teb_list_rdunlock(void) DECLSPEC_HIDDEN;
|
||||
extern FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
|
||||
DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user ) DECLSPEC_HIDDEN;
|
||||
extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 8df7015df9f..05bccf698b6 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -37,6 +37,13 @@
|
||||
#include "wine/debug.h"
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
+
|
||||
+static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
|
||||
+{
|
||||
+ if (!timeout) return "(infinite)";
|
||||
+ return wine_dbgstr_longlong( timeout->QuadPart );
|
||||
+}
|
||||
|
||||
/******************************************************************
|
||||
* RtlRunOnceInitialize (NTDLL.@)
|
||||
@@ -531,13 +538,48 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||
return status;
|
||||
}
|
||||
|
||||
+static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
|
||||
+{
|
||||
+ switch (size)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
|
||||
+ case 2:
|
||||
+ return (*(const USHORT *)addr == *(const USHORT *)cmp);
|
||||
+ case 4:
|
||||
+ return (*(const ULONG *)addr == *(const ULONG *)cmp);
|
||||
+ case 8:
|
||||
+ return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
|
||||
+ }
|
||||
+
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* RtlWaitOnAddress (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
|
||||
const LARGE_INTEGER *timeout )
|
||||
{
|
||||
- return unix_funcs->RtlWaitOnAddress( addr, cmp, size, timeout );
|
||||
+ NTSTATUS ret;
|
||||
+
|
||||
+ TRACE("addr %p cmp %p size %#Ix timeout %s\n", addr, cmp, size, debugstr_timeout( timeout ));
|
||||
+
|
||||
+ if (size != 1 && size != 2 && size != 4 && size != 8)
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ InterlockedExchangePointer( &NtCurrentTeb()->ReservedForPerf, (void *)addr );
|
||||
+
|
||||
+ if (!compare_addr( addr, cmp, size ))
|
||||
+ {
|
||||
+ InterlockedExchangePointer( &NtCurrentTeb()->ReservedForPerf, NULL );
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ ret = NtWaitForAlertByThreadId( addr, timeout );
|
||||
+ InterlockedExchangePointer( &NtCurrentTeb()->ReservedForPerf, NULL );
|
||||
+ if (ret == STATUS_ALERTED) ret = STATUS_SUCCESS;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -545,7 +587,20 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||
*/
|
||||
void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
{
|
||||
- return unix_funcs->RtlWakeAddressAll( addr );
|
||||
+ LIST_ENTRY *entry;
|
||||
+
|
||||
+ TRACE("%p\n", addr);
|
||||
+
|
||||
+ if (!addr) return;
|
||||
+
|
||||
+ teb_list_rdlock();
|
||||
+ for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
|
||||
+ {
|
||||
+ const TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
|
||||
+ if (teb->ReservedForPerf == addr)
|
||||
+ NtAlertThreadByThreadId( teb->ClientId.UniqueThread );
|
||||
+ }
|
||||
+ teb_list_rdunlock();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -553,5 +608,21 @@ void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
*/
|
||||
void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||
{
|
||||
- return unix_funcs->RtlWakeAddressSingle( addr );
|
||||
+ LIST_ENTRY *entry;
|
||||
+
|
||||
+ TRACE("%p\n", addr);
|
||||
+
|
||||
+ if (!addr) return;
|
||||
+
|
||||
+ teb_list_rdlock();
|
||||
+ for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
|
||||
+ {
|
||||
+ const TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
|
||||
+ if (teb->ReservedForPerf == addr)
|
||||
+ {
|
||||
+ NtAlertThreadByThreadId( teb->ClientId.UniqueThread );
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ teb_list_rdunlock();
|
||||
}
|
||||
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
|
||||
index 31cfb43d11f..5ab3121dd2c 100644
|
||||
--- a/dlls/ntdll/unix/loader.c
|
||||
+++ b/dlls/ntdll/unix/loader.c
|
||||
@@ -1511,9 +1511,6 @@ static struct unix_funcs unix_funcs =
|
||||
NtCurrentTeb,
|
||||
DbgUiIssueRemoteBreakin,
|
||||
RtlGetSystemTimePrecise,
|
||||
- RtlWaitOnAddress,
|
||||
- RtlWakeAddressAll,
|
||||
- RtlWakeAddressSingle,
|
||||
fast_RtlpWaitForCriticalSection,
|
||||
fast_RtlpUnWaitCriticalSection,
|
||||
fast_RtlDeleteCriticalSection,
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index e4aa03f94da..2bdd3a196bc 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -77,10 +77,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
|
||||
HANDLE keyed_event = 0;
|
||||
|
||||
-static const LARGE_INTEGER zero_timeout;
|
||||
-
|
||||
-static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
-
|
||||
static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
|
||||
{
|
||||
if (!timeout) return "(infinite)";
|
||||
@@ -190,24 +186,6 @@ static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGE
|
||||
#endif
|
||||
|
||||
|
||||
-static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
|
||||
-{
|
||||
- switch (size)
|
||||
- {
|
||||
- case 1:
|
||||
- return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
|
||||
- case 2:
|
||||
- return (*(const USHORT *)addr == *(const USHORT *)cmp);
|
||||
- case 4:
|
||||
- return (*(const ULONG *)addr == *(const ULONG *)cmp);
|
||||
- case 8:
|
||||
- return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
|
||||
- }
|
||||
-
|
||||
- return FALSE;
|
||||
-}
|
||||
-
|
||||
-
|
||||
/* create a struct security_descriptor and contained information in one contiguous piece of memory */
|
||||
NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||
data_size_t *ret_len )
|
||||
@@ -2678,71 +2656,6 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
-
|
||||
-/* We can't map addresses to futex directly, because an application can wait on
|
||||
- * 8 bytes, and we can't pass all 8 as the compare value to futex(). Instead we
|
||||
- * map all addresses to a small fixed table of futexes. This may result in
|
||||
- * spurious wakes, but the application is already expected to handle those. */
|
||||
-
|
||||
-static int addr_futex_table[256];
|
||||
-
|
||||
-static inline int *hash_addr( const void *addr )
|
||||
-{
|
||||
- ULONG_PTR val = (ULONG_PTR)addr;
|
||||
-
|
||||
- return &addr_futex_table[(val >> 2) & 255];
|
||||
-}
|
||||
-
|
||||
-static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
|
||||
- const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- int *futex;
|
||||
- int val;
|
||||
- struct timespec timespec;
|
||||
- int ret;
|
||||
-
|
||||
- if (!use_futexes())
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- futex = hash_addr( addr );
|
||||
-
|
||||
- /* We must read the previous value of the futex before checking the value
|
||||
- * of the address being waited on. That way, if we receive a wake between
|
||||
- * now and waiting on the futex, we know that val will have changed.
|
||||
- * Use an atomic load so that memory accesses are ordered between this read
|
||||
- * and the increment below. */
|
||||
- val = InterlockedCompareExchange( futex, 0, 0 );
|
||||
- if (!compare_addr( addr, cmp, size ))
|
||||
- return STATUS_SUCCESS;
|
||||
-
|
||||
- if (timeout)
|
||||
- {
|
||||
- timespec_from_timeout( ×pec, timeout );
|
||||
- ret = futex_wait( futex, val, ×pec );
|
||||
- }
|
||||
- else
|
||||
- ret = futex_wait( futex, val, NULL );
|
||||
-
|
||||
- if (ret == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-static inline NTSTATUS fast_wake_addr( const void *addr )
|
||||
-{
|
||||
- int *futex;
|
||||
-
|
||||
- if (!use_futexes())
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- futex = hash_addr( addr );
|
||||
-
|
||||
- InterlockedIncrement( futex );
|
||||
-
|
||||
- futex_wake( futex, INT_MAX );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
#else
|
||||
|
||||
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
@@ -2785,79 +2698,4 @@ NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
-static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
|
||||
- const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-static inline NTSTATUS fast_wake_addr( const void *addr )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlWaitOnAddress (NTDLL.@)
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
|
||||
- const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- select_op_t select_op;
|
||||
- NTSTATUS ret;
|
||||
- timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
||||
-
|
||||
- if (size != 1 && size != 2 && size != 4 && size != 8)
|
||||
- return STATUS_INVALID_PARAMETER;
|
||||
-
|
||||
- if ((ret = fast_wait_addr( addr, cmp, size, timeout )) != STATUS_NOT_IMPLEMENTED)
|
||||
- return ret;
|
||||
-
|
||||
- mutex_lock( &addr_mutex );
|
||||
- if (!compare_addr( addr, cmp, size ))
|
||||
- {
|
||||
- mutex_unlock( &addr_mutex );
|
||||
- return STATUS_SUCCESS;
|
||||
- }
|
||||
-
|
||||
- if (abs_timeout < 0)
|
||||
- {
|
||||
- LARGE_INTEGER now;
|
||||
-
|
||||
- NtQueryPerformanceCounter( &now, NULL );
|
||||
- abs_timeout -= now.QuadPart;
|
||||
- }
|
||||
-
|
||||
- select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
|
||||
- select_op.keyed_event.handle = wine_server_obj_handle( keyed_event );
|
||||
- select_op.keyed_event.key = wine_server_client_ptr( addr );
|
||||
-
|
||||
- return server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE,
|
||||
- abs_timeout, NULL, &addr_mutex, NULL );
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlWakeAddressAll (NTDLL.@)
|
||||
- */
|
||||
-void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
-{
|
||||
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
|
||||
-
|
||||
- mutex_lock( &addr_mutex );
|
||||
- while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
|
||||
- mutex_unlock( &addr_mutex );
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlWakeAddressSingle (NTDLL.@)
|
||||
- */
|
||||
-void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||
-{
|
||||
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
|
||||
-
|
||||
- mutex_lock( &addr_mutex );
|
||||
- NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
|
||||
- mutex_unlock( &addr_mutex );
|
||||
-}
|
||||
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
|
||||
index 7ed3148e4c4..a9c05cbd09b 100644
|
||||
--- a/dlls/ntdll/unixlib.h
|
||||
+++ b/dlls/ntdll/unixlib.h
|
||||
@@ -27,7 +27,7 @@
|
||||
struct _DISPATCHER_CONTEXT;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
-#define NTDLL_UNIXLIB_VERSION 106
|
||||
+#define NTDLL_UNIXLIB_VERSION 107
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
@@ -37,10 +37,6 @@ struct unix_funcs
|
||||
/* other Win32 API functions */
|
||||
NTSTATUS (WINAPI *DbgUiIssueRemoteBreakin)( HANDLE process );
|
||||
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
|
||||
- NTSTATUS (WINAPI *RtlWaitOnAddress)( const void *addr, const void *cmp, SIZE_T size,
|
||||
- const LARGE_INTEGER *timeout );
|
||||
- void (WINAPI *RtlWakeAddressAll)( const void *addr );
|
||||
- void (WINAPI *RtlWakeAddressSingle)( const void *addr );
|
||||
|
||||
/* fast locks */
|
||||
NTSTATUS (CDECL *fast_RtlpWaitForCriticalSection)( RTL_CRITICAL_SECTION *crit, int timeout );
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,933 @@
|
||||
From 9e9f51741ee04bcf8123ae23241ba3c4f8c8b2cf Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:30:52 -0500
|
||||
Subject: [PATCH 10/13] ntdll: Merge critsection.c into sync.c.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/Makefile.in | 1 -
|
||||
dlls/ntdll/critsection.c | 543 ---------------------------------------
|
||||
dlls/ntdll/sync.c | 334 +++++++++++++++++++++++-
|
||||
3 files changed, 333 insertions(+), 545 deletions(-)
|
||||
delete mode 100644 dlls/ntdll/critsection.c
|
||||
|
||||
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
|
||||
index b2f63d9f63a..5ef28d2f722 100644
|
||||
--- a/dlls/ntdll/Makefile.in
|
||||
+++ b/dlls/ntdll/Makefile.in
|
||||
@@ -9,7 +9,6 @@ EXTRADLLFLAGS = -mno-cygwin -nodefaultlibs -Wl,--image-base,0x7bc00000
|
||||
C_SRCS = \
|
||||
actctx.c \
|
||||
atom.c \
|
||||
- critsection.c \
|
||||
crypt.c \
|
||||
debugbuffer.c \
|
||||
directory.c \
|
||||
diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c
|
||||
deleted file mode 100644
|
||||
index fe7d933c0fa..00000000000
|
||||
--- a/dlls/ntdll/critsection.c
|
||||
+++ /dev/null
|
||||
@@ -1,543 +0,0 @@
|
||||
-/*
|
||||
- * Win32 critical sections
|
||||
- *
|
||||
- * Copyright 1998 Alexandre Julliard
|
||||
- *
|
||||
- * This library is free software; you can redistribute it and/or
|
||||
- * modify it under the terms of the GNU Lesser General Public
|
||||
- * License as published by the Free Software Foundation; either
|
||||
- * version 2.1 of the License, or (at your option) any later version.
|
||||
- *
|
||||
- * This library is distributed in the hope that it will be useful,
|
||||
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- * Lesser General Public License for more details.
|
||||
- *
|
||||
- * You should have received a copy of the GNU Lesser General Public
|
||||
- * License along with this library; if not, write to the Free Software
|
||||
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
- */
|
||||
-
|
||||
-#include <assert.h>
|
||||
-#include <errno.h>
|
||||
-#include <stdarg.h>
|
||||
-#include <stdio.h>
|
||||
-#include <sys/types.h>
|
||||
-#include <time.h>
|
||||
-#include "ntstatus.h"
|
||||
-#define WIN32_NO_STATUS
|
||||
-#include "windef.h"
|
||||
-#include "winternl.h"
|
||||
-#include "wine/debug.h"
|
||||
-#include "ntdll_misc.h"
|
||||
-
|
||||
-WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
-WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
-
|
||||
-static inline void small_pause(void)
|
||||
-{
|
||||
-#ifdef __i386__
|
||||
- __asm__ __volatile__( "rep;nop" : : : "memory" );
|
||||
-#else
|
||||
- __asm__ __volatile__( "" : : : "memory" );
|
||||
-#endif
|
||||
-}
|
||||
-
|
||||
-static void *no_debug_info_marker = (void *)(ULONG_PTR)-1;
|
||||
-
|
||||
-static BOOL crit_section_has_debuginfo(const RTL_CRITICAL_SECTION *crit)
|
||||
-{
|
||||
- return crit->DebugInfo != NULL && crit->DebugInfo != no_debug_info_marker;
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * get_semaphore
|
||||
- */
|
||||
-static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- HANDLE ret = crit->LockSemaphore;
|
||||
- if (!ret)
|
||||
- {
|
||||
- HANDLE sem;
|
||||
- if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
|
||||
- if (!(ret = InterlockedCompareExchangePointer( &crit->LockSemaphore, sem, 0 )))
|
||||
- ret = sem;
|
||||
- else
|
||||
- NtClose(sem); /* somebody beat us to it */
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * wait_semaphore
|
||||
- */
|
||||
-static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- NTSTATUS ret;
|
||||
-
|
||||
- /* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
- if (!crit_section_has_debuginfo( crit ) ||
|
||||
- ((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
|
||||
- {
|
||||
- HANDLE sem = get_semaphore( crit );
|
||||
- LARGE_INTEGER time;
|
||||
-
|
||||
- time.QuadPart = timeout * (LONGLONG)-10000000;
|
||||
- ret = NtWaitForSingleObject( sem, FALSE, &time );
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlInitializeCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Initialises a new critical section.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [O] Critical section to initialise
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSectionAndSpinCount(), RtlDeleteCriticalSection(),
|
||||
- * RtlEnterCriticalSection(), RtlLeaveCriticalSection(),
|
||||
- * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return RtlInitializeCriticalSectionEx( crit, 0, 0 );
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlInitializeCriticalSectionAndSpinCount (NTDLL.@)
|
||||
- *
|
||||
- * Initialises a new critical section with a given spin count.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [O] Critical section to initialise
|
||||
- * spincount [I] Spin count for crit
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * NOTES
|
||||
- * Available on NT4 SP3 or later.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(),
|
||||
- * RtlEnterCriticalSection(), RtlLeaveCriticalSection(),
|
||||
- * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION *crit, ULONG spincount )
|
||||
-{
|
||||
- return RtlInitializeCriticalSectionEx( crit, spincount, 0 );
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlInitializeCriticalSectionEx (NTDLL.@)
|
||||
- *
|
||||
- * Initialises a new critical section with a given spin count and flags.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [O] Critical section to initialise.
|
||||
- * spincount [I] Number of times to spin upon contention.
|
||||
- * flags [I] RTL_CRITICAL_SECTION_FLAG_ flags from winnt.h.
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * NOTES
|
||||
- * Available on Vista or later.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(),
|
||||
- * RtlEnterCriticalSection(), RtlLeaveCriticalSection(),
|
||||
- * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags )
|
||||
-{
|
||||
- if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT))
|
||||
- FIXME("(%p,%u,0x%08x) semi-stub\n", crit, spincount, flags);
|
||||
-
|
||||
- /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use
|
||||
- * memory from a static pool to hold the debug info. Then heap.c could pass
|
||||
- * this flag rather than initialising the process heap CS by hand. If this
|
||||
- * is done, then debug info should be managed through Rtlp[Allocate|Free]DebugInfo
|
||||
- * so (e.g.) MakeCriticalSectionGlobal() doesn't free it using HeapFree().
|
||||
- */
|
||||
- if (flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO)
|
||||
- crit->DebugInfo = no_debug_info_marker;
|
||||
- else
|
||||
- {
|
||||
- crit->DebugInfo = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_CRITICAL_SECTION_DEBUG));
|
||||
- if (crit->DebugInfo)
|
||||
- {
|
||||
- crit->DebugInfo->Type = 0;
|
||||
- crit->DebugInfo->CreatorBackTraceIndex = 0;
|
||||
- crit->DebugInfo->CriticalSection = crit;
|
||||
- crit->DebugInfo->ProcessLocksList.Blink = &(crit->DebugInfo->ProcessLocksList);
|
||||
- crit->DebugInfo->ProcessLocksList.Flink = &(crit->DebugInfo->ProcessLocksList);
|
||||
- crit->DebugInfo->EntryCount = 0;
|
||||
- crit->DebugInfo->ContentionCount = 0;
|
||||
- memset( crit->DebugInfo->Spare, 0, sizeof(crit->DebugInfo->Spare) );
|
||||
- }
|
||||
- }
|
||||
- crit->LockCount = -1;
|
||||
- crit->RecursionCount = 0;
|
||||
- crit->OwningThread = 0;
|
||||
- crit->LockSemaphore = 0;
|
||||
- if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0;
|
||||
- crit->SpinCount = spincount & ~0x80000000;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlSetCriticalSectionSpinCount (NTDLL.@)
|
||||
- *
|
||||
- * Sets the spin count of a critical section.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section
|
||||
- * spincount [I] Spin count for crit
|
||||
- *
|
||||
- * RETURNS
|
||||
- * The previous spin count.
|
||||
- *
|
||||
- * NOTES
|
||||
- * If the system is not SMP, spincount is ignored and set to 0.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-ULONG WINAPI RtlSetCriticalSectionSpinCount( RTL_CRITICAL_SECTION *crit, ULONG spincount )
|
||||
-{
|
||||
- ULONG oldspincount = crit->SpinCount;
|
||||
- if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0;
|
||||
- crit->SpinCount = spincount;
|
||||
- return oldspincount;
|
||||
-}
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlDeleteCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Frees the resources used by a critical section.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to free
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- crit->LockCount = -1;
|
||||
- crit->RecursionCount = 0;
|
||||
- crit->OwningThread = 0;
|
||||
- if (crit_section_has_debuginfo( crit ))
|
||||
- {
|
||||
- /* only free the ones we made in here */
|
||||
- if (!crit->DebugInfo->Spare[0])
|
||||
- {
|
||||
- RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
|
||||
- crit->DebugInfo = NULL;
|
||||
- }
|
||||
- if (unix_funcs->fast_RtlDeleteCriticalSection( crit ) == STATUS_NOT_IMPLEMENTED)
|
||||
- NtClose( crit->LockSemaphore );
|
||||
- }
|
||||
- else NtClose( crit->LockSemaphore );
|
||||
- crit->LockSemaphore = 0;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlpWaitForCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Waits for a busy critical section to become free.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to wait for
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * NOTES
|
||||
- * Use RtlEnterCriticalSection() instead of this function as it is often much
|
||||
- * faster.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- LONGLONG timeout = NtCurrentTeb()->Peb->CriticalSectionTimeout.QuadPart / -10000000;
|
||||
-
|
||||
- /* Don't allow blocking on a critical section during process termination */
|
||||
- if (RtlDllShutdownInProgress())
|
||||
- {
|
||||
- WARN( "process %s is shutting down, returning STATUS_SUCCESS\n",
|
||||
- debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer) );
|
||||
- return STATUS_SUCCESS;
|
||||
- }
|
||||
-
|
||||
- for (;;)
|
||||
- {
|
||||
- EXCEPTION_RECORD rec;
|
||||
- NTSTATUS status = wait_semaphore( crit, 5 );
|
||||
- timeout -= 5;
|
||||
-
|
||||
- if ( status == STATUS_TIMEOUT )
|
||||
- {
|
||||
- const char *name = NULL;
|
||||
- if (crit_section_has_debuginfo( crit )) name = (char *)crit->DebugInfo->Spare[0];
|
||||
- if (!name) name = "?";
|
||||
- ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (60 sec)\n",
|
||||
- crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
|
||||
- status = wait_semaphore( crit, 60 );
|
||||
- timeout -= 60;
|
||||
-
|
||||
- if ( status == STATUS_TIMEOUT && TRACE_ON(relay) )
|
||||
- {
|
||||
- ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (5 min)\n",
|
||||
- crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
|
||||
- status = wait_semaphore( crit, 300 );
|
||||
- timeout -= 300;
|
||||
- }
|
||||
- }
|
||||
- if (status == STATUS_WAIT_0) break;
|
||||
-
|
||||
- /* Throw exception only for Wine internal locks */
|
||||
- if (!crit_section_has_debuginfo( crit ) || !crit->DebugInfo->Spare[0]) continue;
|
||||
-
|
||||
- /* only throw deadlock exception if configured timeout is reached */
|
||||
- if (timeout > 0) continue;
|
||||
-
|
||||
- rec.ExceptionCode = STATUS_POSSIBLE_DEADLOCK;
|
||||
- rec.ExceptionFlags = 0;
|
||||
- rec.ExceptionRecord = NULL;
|
||||
- rec.ExceptionAddress = RtlRaiseException; /* sic */
|
||||
- rec.NumberParameters = 1;
|
||||
- rec.ExceptionInformation[0] = (ULONG_PTR)crit;
|
||||
- RtlRaiseException( &rec );
|
||||
- }
|
||||
- if (crit_section_has_debuginfo( crit )) crit->DebugInfo->ContentionCount++;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlpUnWaitCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Notifies other threads waiting on the busy critical section that it has
|
||||
- * become free.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section
|
||||
- *
|
||||
- * RETURNS
|
||||
- * Success: STATUS_SUCCESS.
|
||||
- * Failure: Any error returned by NtReleaseSemaphore()
|
||||
- *
|
||||
- * NOTES
|
||||
- * Use RtlLeaveCriticalSection() instead of this function as it is often much
|
||||
- * faster.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- NTSTATUS ret;
|
||||
-
|
||||
- /* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
- if (!crit_section_has_debuginfo( crit ) ||
|
||||
- ((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
|
||||
- {
|
||||
- HANDLE sem = get_semaphore( crit );
|
||||
- ret = NtReleaseSemaphore( sem, 1, NULL );
|
||||
- }
|
||||
- if (ret) RtlRaiseStatus( ret );
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlEnterCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Enters a critical section, waiting for it to become available if necessary.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to enter
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS. The critical section is held by the caller.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlSetCriticalSectionSpinCount(),
|
||||
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (crit->SpinCount)
|
||||
- {
|
||||
- ULONG count;
|
||||
-
|
||||
- if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS;
|
||||
- for (count = crit->SpinCount; count > 0; count--)
|
||||
- {
|
||||
- if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */
|
||||
- if (crit->LockCount == -1) /* try again */
|
||||
- {
|
||||
- if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done;
|
||||
- }
|
||||
- small_pause();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (InterlockedIncrement( &crit->LockCount ))
|
||||
- {
|
||||
- if (crit->OwningThread == ULongToHandle(GetCurrentThreadId()))
|
||||
- {
|
||||
- crit->RecursionCount++;
|
||||
- return STATUS_SUCCESS;
|
||||
- }
|
||||
-
|
||||
- /* Now wait for it */
|
||||
- RtlpWaitForCriticalSection( crit );
|
||||
- }
|
||||
-done:
|
||||
- crit->OwningThread = ULongToHandle(GetCurrentThreadId());
|
||||
- crit->RecursionCount = 1;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlTryEnterCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Tries to enter a critical section without waiting.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to enter
|
||||
- *
|
||||
- * RETURNS
|
||||
- * Success: TRUE. The critical section is held by the caller.
|
||||
- * Failure: FALSE. The critical section is currently held by another thread.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlLeaveCriticalSection(), RtlSetCriticalSectionSpinCount()
|
||||
- */
|
||||
-BOOL WINAPI RtlTryEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- BOOL ret = FALSE;
|
||||
- if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1)
|
||||
- {
|
||||
- crit->OwningThread = ULongToHandle(GetCurrentThreadId());
|
||||
- crit->RecursionCount = 1;
|
||||
- ret = TRUE;
|
||||
- }
|
||||
- else if (crit->OwningThread == ULongToHandle(GetCurrentThreadId()))
|
||||
- {
|
||||
- InterlockedIncrement( &crit->LockCount );
|
||||
- crit->RecursionCount++;
|
||||
- ret = TRUE;
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlIsCriticalSectionLocked (NTDLL.@)
|
||||
- *
|
||||
- * Checks if the critical section is locked by any thread.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to check.
|
||||
- *
|
||||
- * RETURNS
|
||||
- * Success: TRUE. The critical section is locked.
|
||||
- * Failure: FALSE. The critical section is not locked.
|
||||
- */
|
||||
-BOOL WINAPI RtlIsCriticalSectionLocked( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return crit->RecursionCount != 0;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlIsCriticalSectionLockedByThread (NTDLL.@)
|
||||
- *
|
||||
- * Checks if the critical section is locked by the current thread.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to check.
|
||||
- *
|
||||
- * RETURNS
|
||||
- * Success: TRUE. The critical section is locked.
|
||||
- * Failure: FALSE. The critical section is not locked.
|
||||
- */
|
||||
-BOOL WINAPI RtlIsCriticalSectionLockedByThread( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return crit->OwningThread == ULongToHandle(GetCurrentThreadId()) &&
|
||||
- crit->RecursionCount;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/***********************************************************************
|
||||
- * RtlLeaveCriticalSection (NTDLL.@)
|
||||
- *
|
||||
- * Leaves a critical section.
|
||||
- *
|
||||
- * PARAMS
|
||||
- * crit [I/O] Critical section to leave.
|
||||
- *
|
||||
- * RETURNS
|
||||
- * STATUS_SUCCESS.
|
||||
- *
|
||||
- * SEE
|
||||
- * RtlInitializeCriticalSectionEx(),
|
||||
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
|
||||
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
|
||||
- * RtlSetCriticalSectionSpinCount(), RtlTryEnterCriticalSection()
|
||||
- */
|
||||
-NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (--crit->RecursionCount)
|
||||
- {
|
||||
- if (crit->RecursionCount > 0) InterlockedDecrement( &crit->LockCount );
|
||||
- else ERR( "section %p is not acquired\n", crit );
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- crit->OwningThread = 0;
|
||||
- if (InterlockedDecrement( &crit->LockCount ) >= 0)
|
||||
- {
|
||||
- /* someone is waiting */
|
||||
- RtlpUnWaitCriticalSection( crit );
|
||||
- }
|
||||
- }
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 05bccf698b6..ea327172b86 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -2,7 +2,7 @@
|
||||
* Process synchronisation
|
||||
*
|
||||
* Copyright 1996, 1997, 1998 Marcus Meissner
|
||||
- * Copyright 1997, 1999 Alexandre Julliard
|
||||
+ * Copyright 1997, 1998, 1999 Alexandre Julliard
|
||||
* Copyright 1999, 2000 Juergen Schmied
|
||||
* Copyright 2003 Eric Pouech
|
||||
*
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
+WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
|
||||
{
|
||||
@@ -626,3 +627,334 @@ void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||
}
|
||||
teb_list_rdunlock();
|
||||
}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * Critical sections
|
||||
+ ***********************************************************************/
|
||||
+
|
||||
+
|
||||
+static void *no_debug_info_marker = (void *)(ULONG_PTR)-1;
|
||||
+
|
||||
+static BOOL crit_section_has_debuginfo( const RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ return crit->DebugInfo != NULL && crit->DebugInfo != no_debug_info_marker;
|
||||
+}
|
||||
+
|
||||
+static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ HANDLE ret = crit->LockSemaphore;
|
||||
+ if (!ret)
|
||||
+ {
|
||||
+ HANDLE sem;
|
||||
+ if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
|
||||
+ if (!(ret = InterlockedCompareExchangePointer( &crit->LockSemaphore, sem, 0 )))
|
||||
+ ret = sem;
|
||||
+ else
|
||||
+ NtClose(sem); /* somebody beat us to it */
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
+{
|
||||
+ NTSTATUS ret;
|
||||
+
|
||||
+ /* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
+ if (!crit_section_has_debuginfo( crit ) ||
|
||||
+ ((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
|
||||
+ {
|
||||
+ HANDLE sem = get_semaphore( crit );
|
||||
+ LARGE_INTEGER time;
|
||||
+
|
||||
+ time.QuadPart = timeout * (LONGLONG)-10000000;
|
||||
+ ret = NtWaitForSingleObject( sem, FALSE, &time );
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlInitializeCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ return RtlInitializeCriticalSectionEx( crit, 0, 0 );
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlInitializeCriticalSectionAndSpinCount (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION *crit, ULONG spincount )
|
||||
+{
|
||||
+ return RtlInitializeCriticalSectionEx( crit, spincount, 0 );
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlInitializeCriticalSectionEx (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags )
|
||||
+{
|
||||
+ if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT))
|
||||
+ FIXME("(%p,%u,0x%08x) semi-stub\n", crit, spincount, flags);
|
||||
+
|
||||
+ /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use
|
||||
+ * memory from a static pool to hold the debug info. Then heap.c could pass
|
||||
+ * this flag rather than initialising the process heap CS by hand. If this
|
||||
+ * is done, then debug info should be managed through Rtlp[Allocate|Free]DebugInfo
|
||||
+ * so (e.g.) MakeCriticalSectionGlobal() doesn't free it using HeapFree().
|
||||
+ */
|
||||
+ if (flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO)
|
||||
+ crit->DebugInfo = no_debug_info_marker;
|
||||
+ else
|
||||
+ {
|
||||
+ crit->DebugInfo = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(RTL_CRITICAL_SECTION_DEBUG ));
|
||||
+ if (crit->DebugInfo)
|
||||
+ {
|
||||
+ crit->DebugInfo->Type = 0;
|
||||
+ crit->DebugInfo->CreatorBackTraceIndex = 0;
|
||||
+ crit->DebugInfo->CriticalSection = crit;
|
||||
+ crit->DebugInfo->ProcessLocksList.Blink = &crit->DebugInfo->ProcessLocksList;
|
||||
+ crit->DebugInfo->ProcessLocksList.Flink = &crit->DebugInfo->ProcessLocksList;
|
||||
+ crit->DebugInfo->EntryCount = 0;
|
||||
+ crit->DebugInfo->ContentionCount = 0;
|
||||
+ memset( crit->DebugInfo->Spare, 0, sizeof(crit->DebugInfo->Spare) );
|
||||
+ }
|
||||
+ }
|
||||
+ crit->LockCount = -1;
|
||||
+ crit->RecursionCount = 0;
|
||||
+ crit->OwningThread = 0;
|
||||
+ crit->LockSemaphore = 0;
|
||||
+ if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0;
|
||||
+ crit->SpinCount = spincount & ~0x80000000;
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlSetCriticalSectionSpinCount (NTDLL.@)
|
||||
+ */
|
||||
+ULONG WINAPI RtlSetCriticalSectionSpinCount( RTL_CRITICAL_SECTION *crit, ULONG spincount )
|
||||
+{
|
||||
+ ULONG oldspincount = crit->SpinCount;
|
||||
+ if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0;
|
||||
+ crit->SpinCount = spincount;
|
||||
+ return oldspincount;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlDeleteCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ crit->LockCount = -1;
|
||||
+ crit->RecursionCount = 0;
|
||||
+ crit->OwningThread = 0;
|
||||
+ if (crit_section_has_debuginfo( crit ))
|
||||
+ {
|
||||
+ /* only free the ones we made in here */
|
||||
+ if (!crit->DebugInfo->Spare[0])
|
||||
+ {
|
||||
+ RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
|
||||
+ crit->DebugInfo = NULL;
|
||||
+ }
|
||||
+ if (unix_funcs->fast_RtlDeleteCriticalSection( crit ) == STATUS_NOT_IMPLEMENTED)
|
||||
+ NtClose( crit->LockSemaphore );
|
||||
+ }
|
||||
+ else NtClose( crit->LockSemaphore );
|
||||
+ crit->LockSemaphore = 0;
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlpWaitForCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ LONGLONG timeout = NtCurrentTeb()->Peb->CriticalSectionTimeout.QuadPart / -10000000;
|
||||
+
|
||||
+ /* Don't allow blocking on a critical section during process termination */
|
||||
+ if (RtlDllShutdownInProgress())
|
||||
+ {
|
||||
+ WARN( "process %s is shutting down, returning STATUS_SUCCESS\n",
|
||||
+ debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer) );
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ EXCEPTION_RECORD rec;
|
||||
+ NTSTATUS status = wait_semaphore( crit, 5 );
|
||||
+ timeout -= 5;
|
||||
+
|
||||
+ if ( status == STATUS_TIMEOUT )
|
||||
+ {
|
||||
+ const char *name = NULL;
|
||||
+ if (crit_section_has_debuginfo( crit )) name = (char *)crit->DebugInfo->Spare[0];
|
||||
+ if (!name) name = "?";
|
||||
+ ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (60 sec)\n",
|
||||
+ crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
|
||||
+ status = wait_semaphore( crit, 60 );
|
||||
+ timeout -= 60;
|
||||
+
|
||||
+ if ( status == STATUS_TIMEOUT && TRACE_ON(relay) )
|
||||
+ {
|
||||
+ ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (5 min)\n",
|
||||
+ crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
|
||||
+ status = wait_semaphore( crit, 300 );
|
||||
+ timeout -= 300;
|
||||
+ }
|
||||
+ }
|
||||
+ if (status == STATUS_WAIT_0) break;
|
||||
+
|
||||
+ /* Throw exception only for Wine internal locks */
|
||||
+ if (!crit_section_has_debuginfo( crit ) || !crit->DebugInfo->Spare[0]) continue;
|
||||
+
|
||||
+ /* only throw deadlock exception if configured timeout is reached */
|
||||
+ if (timeout > 0) continue;
|
||||
+
|
||||
+ rec.ExceptionCode = STATUS_POSSIBLE_DEADLOCK;
|
||||
+ rec.ExceptionFlags = 0;
|
||||
+ rec.ExceptionRecord = NULL;
|
||||
+ rec.ExceptionAddress = RtlRaiseException; /* sic */
|
||||
+ rec.NumberParameters = 1;
|
||||
+ rec.ExceptionInformation[0] = (ULONG_PTR)crit;
|
||||
+ RtlRaiseException( &rec );
|
||||
+ }
|
||||
+ if (crit_section_has_debuginfo( crit )) crit->DebugInfo->ContentionCount++;
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlpUnWaitCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ NTSTATUS ret;
|
||||
+
|
||||
+ /* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
+ if (!crit_section_has_debuginfo( crit ) ||
|
||||
+ ((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
|
||||
+ {
|
||||
+ HANDLE sem = get_semaphore( crit );
|
||||
+ ret = NtReleaseSemaphore( sem, 1, NULL );
|
||||
+ }
|
||||
+ if (ret) RtlRaiseStatus( ret );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static inline void small_pause(void)
|
||||
+{
|
||||
+#ifdef __i386__
|
||||
+ __asm__ __volatile__( "rep;nop" : : : "memory" );
|
||||
+#else
|
||||
+ __asm__ __volatile__( "" : : : "memory" );
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlEnterCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ if (crit->SpinCount)
|
||||
+ {
|
||||
+ ULONG count;
|
||||
+
|
||||
+ if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS;
|
||||
+ for (count = crit->SpinCount; count > 0; count--)
|
||||
+ {
|
||||
+ if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */
|
||||
+ if (crit->LockCount == -1) /* try again */
|
||||
+ {
|
||||
+ if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done;
|
||||
+ }
|
||||
+ small_pause();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (InterlockedIncrement( &crit->LockCount ))
|
||||
+ {
|
||||
+ if (crit->OwningThread == ULongToHandle(GetCurrentThreadId()))
|
||||
+ {
|
||||
+ crit->RecursionCount++;
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ /* Now wait for it */
|
||||
+ RtlpWaitForCriticalSection( crit );
|
||||
+ }
|
||||
+done:
|
||||
+ crit->OwningThread = ULongToHandle(GetCurrentThreadId());
|
||||
+ crit->RecursionCount = 1;
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlTryEnterCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+BOOL WINAPI RtlTryEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ BOOL ret = FALSE;
|
||||
+ if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1)
|
||||
+ {
|
||||
+ crit->OwningThread = ULongToHandle(GetCurrentThreadId());
|
||||
+ crit->RecursionCount = 1;
|
||||
+ ret = TRUE;
|
||||
+ }
|
||||
+ else if (crit->OwningThread == ULongToHandle(GetCurrentThreadId()))
|
||||
+ {
|
||||
+ InterlockedIncrement( &crit->LockCount );
|
||||
+ crit->RecursionCount++;
|
||||
+ ret = TRUE;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlIsCriticalSectionLocked (NTDLL.@)
|
||||
+ */
|
||||
+BOOL WINAPI RtlIsCriticalSectionLocked( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ return crit->RecursionCount != 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlIsCriticalSectionLockedByThread (NTDLL.@)
|
||||
+ */
|
||||
+BOOL WINAPI RtlIsCriticalSectionLockedByThread( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ return crit->OwningThread == ULongToHandle(GetCurrentThreadId()) &&
|
||||
+ crit->RecursionCount;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * RtlLeaveCriticalSection (NTDLL.@)
|
||||
+ */
|
||||
+NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ if (--crit->RecursionCount)
|
||||
+ {
|
||||
+ if (crit->RecursionCount > 0) InterlockedDecrement( &crit->LockCount );
|
||||
+ else ERR( "section %p is not acquired\n", crit );
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ crit->OwningThread = 0;
|
||||
+ if (InterlockedDecrement( &crit->LockCount ) >= 0)
|
||||
+ {
|
||||
+ /* someone is waiting */
|
||||
+ RtlpUnWaitCriticalSection( crit );
|
||||
+ }
|
||||
+ }
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,258 @@
|
||||
From 8b1502d1fc5a6ccb748a8ada38784e79f5612811 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:38:09 -0500
|
||||
Subject: [PATCH 11/13] ntdll: Reimplement the critical section fast path on
|
||||
top of Win32 futexes.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/sync.c | 35 +++++++----
|
||||
dlls/ntdll/unix/loader.c | 3 -
|
||||
dlls/ntdll/unix/sync.c | 109 ---------------------------------
|
||||
dlls/ntdll/unix/unix_private.h | 3 -
|
||||
dlls/ntdll/unixlib.h | 5 +-
|
||||
5 files changed, 24 insertions(+), 131 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index ea327172b86..d7976a742c6 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -658,19 +658,26 @@ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
|
||||
static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
{
|
||||
- NTSTATUS ret;
|
||||
+ LARGE_INTEGER time = {.QuadPart = timeout * (LONGLONG)-10000000};
|
||||
|
||||
/* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
- if (!crit_section_has_debuginfo( crit ) ||
|
||||
- ((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
|
||||
+ if (!crit_section_has_debuginfo( crit ))
|
||||
{
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
- LARGE_INTEGER time;
|
||||
-
|
||||
- time.QuadPart = timeout * (LONGLONG)-10000000;
|
||||
- ret = NtWaitForSingleObject( sem, FALSE, &time );
|
||||
+ return NtWaitForSingleObject( sem, FALSE, &time );
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int *lock = (int *)&crit->LockSemaphore;
|
||||
+ while (!InterlockedCompareExchange( lock, 0, 1 ))
|
||||
+ {
|
||||
+ static const int zero;
|
||||
+ /* this may wait longer than specified in case of multiple wake-ups */
|
||||
+ if (RtlWaitOnAddress( (int *)&crit->LockSemaphore, &zero, sizeof(int), &time ) == STATUS_TIMEOUT)
|
||||
+ return STATUS_TIMEOUT;
|
||||
+ }
|
||||
+ return STATUS_WAIT_0;
|
||||
}
|
||||
- return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -760,8 +767,6 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
|
||||
crit->DebugInfo = NULL;
|
||||
}
|
||||
- if (unix_funcs->fast_RtlDeleteCriticalSection( crit ) == STATUS_NOT_IMPLEMENTED)
|
||||
- NtClose( crit->LockSemaphore );
|
||||
}
|
||||
else NtClose( crit->LockSemaphore );
|
||||
crit->LockSemaphore = 0;
|
||||
@@ -837,12 +842,18 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
NTSTATUS ret;
|
||||
|
||||
/* debug info is cleared by MakeCriticalSectionGlobal */
|
||||
- if (!crit_section_has_debuginfo( crit ) ||
|
||||
- ((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
|
||||
+ if (!crit_section_has_debuginfo( crit ))
|
||||
{
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
ret = NtReleaseSemaphore( sem, 1, NULL );
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ int *lock = (int *)&crit->LockSemaphore;
|
||||
+ *lock = 1;
|
||||
+ RtlWakeAddressSingle( lock );
|
||||
+ ret = STATUS_SUCCESS;
|
||||
+ }
|
||||
if (ret) RtlRaiseStatus( ret );
|
||||
return ret;
|
||||
}
|
||||
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
|
||||
index 5ab3121dd2c..ac4efc74e5e 100644
|
||||
--- a/dlls/ntdll/unix/loader.c
|
||||
+++ b/dlls/ntdll/unix/loader.c
|
||||
@@ -1511,9 +1511,6 @@ static struct unix_funcs unix_funcs =
|
||||
NtCurrentTeb,
|
||||
DbgUiIssueRemoteBreakin,
|
||||
RtlGetSystemTimePrecise,
|
||||
- fast_RtlpWaitForCriticalSection,
|
||||
- fast_RtlpUnWaitCriticalSection,
|
||||
- fast_RtlDeleteCriticalSection,
|
||||
fast_RtlTryAcquireSRWLockExclusive,
|
||||
fast_RtlAcquireSRWLockExclusive,
|
||||
fast_RtlTryAcquireSRWLockShared,
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index 2bdd3a196bc..0f45fdecdca 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -2251,115 +2251,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||
}
|
||||
|
||||
|
||||
-#ifdef __linux__
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- int val;
|
||||
- struct timespec timespec;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- timespec.tv_sec = timeout;
|
||||
- timespec.tv_nsec = 0;
|
||||
- while ((val = InterlockedCompareExchange( (int *)&crit->LockSemaphore, 0, 1 )) != 1)
|
||||
- {
|
||||
- /* note: this may wait longer than specified in case of signals or */
|
||||
- /* multiple wake-ups, but that shouldn't be a problem */
|
||||
- if (futex_wait( (int *)&crit->LockSemaphore, val, ×pec ) == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- }
|
||||
- return STATUS_WAIT_0;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- *(int *)&crit->LockSemaphore = 1;
|
||||
- futex_wake( (int *)&crit->LockSemaphore, 1 );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-#elif defined(__APPLE__)
|
||||
-
|
||||
-static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_t ret = *(int *)&crit->LockSemaphore;
|
||||
- if (!ret)
|
||||
- {
|
||||
- semaphore_t sem;
|
||||
- if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) return 0;
|
||||
- if (!(ret = InterlockedCompareExchange( (int *)&crit->LockSemaphore, sem, 0 )))
|
||||
- ret = sem;
|
||||
- else
|
||||
- semaphore_destroy( mach_task_self(), sem ); /* somebody beat us to it */
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- mach_timespec_t timespec;
|
||||
- semaphore_t sem = get_mach_semaphore( crit );
|
||||
-
|
||||
- timespec.tv_sec = timeout;
|
||||
- timespec.tv_nsec = 0;
|
||||
- for (;;)
|
||||
- {
|
||||
- switch( semaphore_timedwait( sem, timespec ))
|
||||
- {
|
||||
- case KERN_SUCCESS:
|
||||
- return STATUS_WAIT_0;
|
||||
- case KERN_ABORTED:
|
||||
- continue; /* got a signal, restart */
|
||||
- case KERN_OPERATION_TIMED_OUT:
|
||||
- return STATUS_TIMEOUT;
|
||||
- default:
|
||||
- return STATUS_INVALID_HANDLE;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_t sem = get_mach_semaphore( crit );
|
||||
- semaphore_signal( sem );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_destroy( mach_task_self(), *(int *)&crit->LockSemaphore );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-#else /* __APPLE__ */
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
#ifdef __linux__
|
||||
|
||||
/* Futex-based SRW lock implementation:
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 9e94c0ec13c..0f833b5a51b 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -93,9 +93,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON
|
||||
extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
|
||||
index a9c05cbd09b..a8dad0d0fcf 100644
|
||||
--- a/dlls/ntdll/unixlib.h
|
||||
+++ b/dlls/ntdll/unixlib.h
|
||||
@@ -27,7 +27,7 @@
|
||||
struct _DISPATCHER_CONTEXT;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
-#define NTDLL_UNIXLIB_VERSION 107
|
||||
+#define NTDLL_UNIXLIB_VERSION 108
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
@@ -39,9 +39,6 @@ struct unix_funcs
|
||||
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
|
||||
|
||||
/* fast locks */
|
||||
- NTSTATUS (CDECL *fast_RtlpWaitForCriticalSection)( RTL_CRITICAL_SECTION *crit, int timeout );
|
||||
- NTSTATUS (CDECL *fast_RtlpUnWaitCriticalSection)( RTL_CRITICAL_SECTION *crit );
|
||||
- NTSTATUS (CDECL *fast_RtlDeleteCriticalSection)( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
NTSTATUS (CDECL *fast_RtlAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,229 @@
|
||||
From 10eabed1355cf47d4eae042e775c8005a67b88d7 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 31 Aug 2020 23:55:29 -0500
|
||||
Subject: [PATCH 12/13] ntdll: Get rid of the direct futex path for condition
|
||||
variables.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/sync.c | 24 ++++--------
|
||||
dlls/ntdll/unix/loader.c | 2 -
|
||||
dlls/ntdll/unix/sync.c | 71 ----------------------------------
|
||||
dlls/ntdll/unix/unix_private.h | 3 --
|
||||
dlls/ntdll/unixlib.h | 5 +--
|
||||
5 files changed, 9 insertions(+), 96 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index d7976a742c6..133ae6d4ead 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -450,11 +450,8 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
*/
|
||||
void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
{
|
||||
- if (unix_funcs->fast_RtlWakeConditionVariable( variable, 1 ) == STATUS_NOT_IMPLEMENTED)
|
||||
- {
|
||||
- InterlockedIncrement( (int *)&variable->Ptr );
|
||||
- RtlWakeAddressSingle( variable );
|
||||
- }
|
||||
+ InterlockedIncrement( (int *)&variable->Ptr );
|
||||
+ RtlWakeAddressSingle( variable );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -464,11 +461,8 @@ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
*/
|
||||
void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
{
|
||||
- if (unix_funcs->fast_RtlWakeConditionVariable( variable, INT_MAX ) == STATUS_NOT_IMPLEMENTED)
|
||||
- {
|
||||
- InterlockedIncrement( (int *)&variable->Ptr );
|
||||
- RtlWakeAddressAll( variable );
|
||||
- }
|
||||
+ InterlockedIncrement( (int *)&variable->Ptr );
|
||||
+ RtlWakeAddressAll( variable );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -489,12 +483,11 @@ void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, RTL_CRITICAL_SECTION *crit,
|
||||
const LARGE_INTEGER *timeout )
|
||||
{
|
||||
- const void *value = variable->Ptr;
|
||||
+ int value = *(int *)&variable->Ptr;
|
||||
NTSTATUS status;
|
||||
|
||||
RtlLeaveCriticalSection( crit );
|
||||
- if ((status = unix_funcs->fast_wait_cv( variable, value, timeout )) == STATUS_NOT_IMPLEMENTED)
|
||||
- status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
|
||||
+ status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
|
||||
RtlEnterCriticalSection( crit );
|
||||
return status;
|
||||
}
|
||||
@@ -521,7 +514,7 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R
|
||||
NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, RTL_SRWLOCK *lock,
|
||||
const LARGE_INTEGER *timeout, ULONG flags )
|
||||
{
|
||||
- const void *value = variable->Ptr;
|
||||
+ int value = *(int *)&variable->Ptr;
|
||||
NTSTATUS status;
|
||||
|
||||
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
|
||||
@@ -529,8 +522,7 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||
else
|
||||
RtlReleaseSRWLockExclusive( lock );
|
||||
|
||||
- if ((status = unix_funcs->fast_wait_cv( variable, value, timeout )) == STATUS_NOT_IMPLEMENTED)
|
||||
- status = RtlWaitOnAddress( variable, &value, sizeof(value), timeout );
|
||||
+ status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
|
||||
|
||||
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
|
||||
RtlAcquireSRWLockShared( lock );
|
||||
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
|
||||
index ac4efc74e5e..1633aeb97eb 100644
|
||||
--- a/dlls/ntdll/unix/loader.c
|
||||
+++ b/dlls/ntdll/unix/loader.c
|
||||
@@ -1517,8 +1517,6 @@ static struct unix_funcs unix_funcs =
|
||||
fast_RtlAcquireSRWLockShared,
|
||||
fast_RtlReleaseSRWLockExclusive,
|
||||
fast_RtlReleaseSRWLockShared,
|
||||
- fast_RtlWakeConditionVariable,
|
||||
- fast_wait_cv,
|
||||
ntdll_atan,
|
||||
ntdll_ceil,
|
||||
ntdll_cos,
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index 0f45fdecdca..3645c9f9549 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -166,23 +166,6 @@ static int *get_futex(void **ptr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- LARGE_INTEGER now;
|
||||
- timeout_t diff;
|
||||
-
|
||||
- if (timeout->QuadPart > 0)
|
||||
- {
|
||||
- NtQuerySystemTime( &now );
|
||||
- diff = timeout->QuadPart - now.QuadPart;
|
||||
- }
|
||||
- else
|
||||
- diff = -timeout->QuadPart;
|
||||
-
|
||||
- timespec->tv_sec = diff / TICKSPERSEC;
|
||||
- timespec->tv_nsec = (diff % TICKSPERSEC) * 100;
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2503,50 +2486,6 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
-NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- const char *value_ptr;
|
||||
- int aligned_value, *futex;
|
||||
- struct timespec timespec;
|
||||
- int ret;
|
||||
-
|
||||
- if (!use_futexes())
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &variable->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- value_ptr = (const char *)&value;
|
||||
- value_ptr += ((ULONG_PTR)futex) - ((ULONG_PTR)&variable->Ptr);
|
||||
- aligned_value = *(int *)value_ptr;
|
||||
-
|
||||
- if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
|
||||
- {
|
||||
- timespec_from_timeout( ×pec, timeout );
|
||||
- ret = futex_wait( futex, aligned_value, ×pec );
|
||||
- }
|
||||
- else
|
||||
- ret = futex_wait( futex, aligned_value, NULL );
|
||||
-
|
||||
- if (ret == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- return STATUS_WAIT_0;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
|
||||
-{
|
||||
- int *futex;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &variable->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- InterlockedIncrement( futex );
|
||||
- futex_wake( futex, count );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
#else
|
||||
|
||||
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
@@ -2579,14 +2518,4 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
-NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 0f833b5a51b..4462c3ad218 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -99,10 +99,7 @@ extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLS
|
||||
extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count ) DECLSPEC_HIDDEN;
|
||||
extern LONGLONG CDECL fast_RtlGetSystemTimePrecise(void) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value,
|
||||
- const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *size ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL get_startup_info( startup_info_t *info, SIZE_T *total_size, SIZE_T *info_size ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
|
||||
index a8dad0d0fcf..6116f408572 100644
|
||||
--- a/dlls/ntdll/unixlib.h
|
||||
+++ b/dlls/ntdll/unixlib.h
|
||||
@@ -27,7 +27,7 @@
|
||||
struct _DISPATCHER_CONTEXT;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
-#define NTDLL_UNIXLIB_VERSION 108
|
||||
+#define NTDLL_UNIXLIB_VERSION 109
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
@@ -45,9 +45,6 @@ struct unix_funcs
|
||||
NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlWakeConditionVariable)( RTL_CONDITION_VARIABLE *variable, int count );
|
||||
- NTSTATUS (CDECL *fast_wait_cv)( RTL_CONDITION_VARIABLE *variable, const void *value,
|
||||
- const LARGE_INTEGER *timeout );
|
||||
|
||||
/* math functions */
|
||||
double (CDECL *atan)( double d );
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,856 @@
|
||||
From 4450fe4cd6c48fcd3293c7ae0c2836640d383eaa Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Sun, 22 Nov 2020 20:51:10 -0600
|
||||
Subject: [PATCH 13/13] ntdll: Reimplement SRW locks on top of Win32 futexes.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/sync.c | 316 +++++++++++++++------------------
|
||||
dlls/ntdll/unix/loader.c | 6 -
|
||||
dlls/ntdll/unix/sync.c | 309 --------------------------------
|
||||
dlls/ntdll/unix/unix_private.h | 6 -
|
||||
dlls/ntdll/unixlib.h | 8 -
|
||||
include/winbase.h | 24 +++
|
||||
6 files changed, 166 insertions(+), 503 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 133ae6d4ead..f792c8a2fb0 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -161,127 +161,23 @@ DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN fu
|
||||
return RtlRunOnceComplete( once, 0, context ? *context : NULL );
|
||||
}
|
||||
|
||||
-
|
||||
-/* SRW locks implementation
|
||||
- *
|
||||
- * The memory layout used by the lock is:
|
||||
- *
|
||||
- * 32 31 16 0
|
||||
- * ________________ ________________
|
||||
- * | X| #exclusive | #shared |
|
||||
- * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
- * Since there is no space left for a separate counter of shared access
|
||||
- * threads inside the locked section the #shared field is used for multiple
|
||||
- * purposes. The following table lists all possible states the lock can be
|
||||
- * in, notation: [X, #exclusive, #shared]:
|
||||
- *
|
||||
- * [0, 0, N] -> locked by N shared access threads, if N=0 it's unlocked
|
||||
- * [0, >=1, >=1] -> threads are requesting exclusive locks, but there are
|
||||
- * still shared access threads inside. #shared should not be incremented
|
||||
- * anymore!
|
||||
- * [1, >=1, >=0] -> lock is owned by an exclusive thread and the #shared
|
||||
- * counter can be used again to count the number of threads waiting in the
|
||||
- * queue for shared access.
|
||||
- *
|
||||
- * the following states are invalid and will never occur:
|
||||
- * [0, >=1, 0], [1, 0, >=0]
|
||||
- *
|
||||
- * The main problem arising from the fact that we have no separate counter
|
||||
- * of shared access threads inside the locked section is that in the state
|
||||
- * [0, >=1, >=1] above we cannot add additional waiting threads to the
|
||||
- * shared access queue - it wouldn't be possible to distinguish waiting
|
||||
- * threads and those that are still inside. To solve this problem the lock
|
||||
- * uses the following approach: a thread that isn't able to allocate a
|
||||
- * shared lock just uses the exclusive queue instead. As soon as the thread
|
||||
- * is woken up it is in the state [1, >=1, >=0]. In this state it's again
|
||||
- * possible to use the shared access queue. The thread atomically moves
|
||||
- * itself to the shared access queue and releases the exclusive lock, so
|
||||
- * that the "real" exclusive access threads have a chance. As soon as they
|
||||
- * are all ready the shared access threads are processed.
|
||||
- */
|
||||
-
|
||||
-#define SRWLOCK_MASK_IN_EXCLUSIVE 0x80000000
|
||||
-#define SRWLOCK_MASK_EXCLUSIVE_QUEUE 0x7fff0000
|
||||
-#define SRWLOCK_MASK_SHARED_QUEUE 0x0000ffff
|
||||
-#define SRWLOCK_RES_EXCLUSIVE 0x00010000
|
||||
-#define SRWLOCK_RES_SHARED 0x00000001
|
||||
-
|
||||
-#ifdef WORDS_BIGENDIAN
|
||||
-#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1))
|
||||
-#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1))
|
||||
-#else
|
||||
-#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1))
|
||||
-#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1))
|
||||
-#endif
|
||||
-
|
||||
-static inline void srwlock_check_invalid( unsigned int val )
|
||||
-{
|
||||
- /* Throw exception if it's impossible to acquire/release this lock. */
|
||||
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) == SRWLOCK_MASK_EXCLUSIVE_QUEUE ||
|
||||
- (val & SRWLOCK_MASK_SHARED_QUEUE) == SRWLOCK_MASK_SHARED_QUEUE)
|
||||
- RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);
|
||||
-}
|
||||
-
|
||||
-static inline unsigned int srwlock_lock_exclusive( unsigned int *dest, int incr )
|
||||
-{
|
||||
- unsigned int val, tmp;
|
||||
- /* Atomically modifies the value of *dest by adding incr. If the shared
|
||||
- * queue is empty and there are threads waiting for exclusive access, then
|
||||
- * sets the mark SRWLOCK_MASK_IN_EXCLUSIVE to signal other threads that
|
||||
- * they are allowed again to use the shared queue counter. */
|
||||
- for (val = *dest;; val = tmp)
|
||||
- {
|
||||
- tmp = val + incr;
|
||||
- srwlock_check_invalid( tmp );
|
||||
- if ((tmp & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(tmp & SRWLOCK_MASK_SHARED_QUEUE))
|
||||
- tmp |= SRWLOCK_MASK_IN_EXCLUSIVE;
|
||||
- if ((tmp = InterlockedCompareExchange( (int *)dest, tmp, val )) == val)
|
||||
- break;
|
||||
- }
|
||||
- return val;
|
||||
-}
|
||||
-
|
||||
-static inline unsigned int srwlock_unlock_exclusive( unsigned int *dest, int incr )
|
||||
-{
|
||||
- unsigned int val, tmp;
|
||||
- /* Atomically modifies the value of *dest by adding incr. If the queue of
|
||||
- * threads waiting for exclusive access is empty, then remove the
|
||||
- * SRWLOCK_MASK_IN_EXCLUSIVE flag (only the shared queue counter will
|
||||
- * remain). */
|
||||
- for (val = *dest;; val = tmp)
|
||||
- {
|
||||
- tmp = val + incr;
|
||||
- srwlock_check_invalid( tmp );
|
||||
- if (!(tmp & SRWLOCK_MASK_EXCLUSIVE_QUEUE))
|
||||
- tmp &= SRWLOCK_MASK_SHARED_QUEUE;
|
||||
- if ((tmp = InterlockedCompareExchange( (int *)dest, tmp, val )) == val)
|
||||
- break;
|
||||
- }
|
||||
- return val;
|
||||
-}
|
||||
-
|
||||
-static inline void srwlock_leave_exclusive( RTL_SRWLOCK *lock, unsigned int val )
|
||||
-{
|
||||
- /* Used when a thread leaves an exclusive section. If there are other
|
||||
- * exclusive access threads they are processed first, followed by
|
||||
- * the shared waiters. */
|
||||
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
|
||||
- NtReleaseKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
|
||||
- else
|
||||
- {
|
||||
- val &= SRWLOCK_MASK_SHARED_QUEUE; /* remove SRWLOCK_MASK_IN_EXCLUSIVE */
|
||||
- while (val--)
|
||||
- NtReleaseKeyedEvent( 0, srwlock_key_shared(lock), FALSE, NULL );
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static inline void srwlock_leave_shared( RTL_SRWLOCK *lock, unsigned int val )
|
||||
-{
|
||||
- /* Wake up one exclusive thread as soon as the last shared access thread
|
||||
- * has left. */
|
||||
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_SHARED_QUEUE))
|
||||
- NtReleaseKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
|
||||
-}
|
||||
+struct srw_lock
|
||||
+{
|
||||
+ short exclusive_waiters;
|
||||
+
|
||||
+ /* Number of shared owners, or -1 if owned exclusive.
|
||||
+ *
|
||||
+ * Sadly Windows has no equivalent to FUTEX_WAIT_BITSET, so in order to wake
|
||||
+ * up *only* exclusive or *only* shared waiters (and thus avoid spurious
|
||||
+ * wakeups), we need to wait on two different addresses.
|
||||
+ * RtlAcquireSRWLockShared() needs to know the values of "exclusive_waiters"
|
||||
+ * and "owners", but RtlAcquireSRWLockExclusive() only needs to know the
|
||||
+ * value of "owners", so the former can wait on the entire structure, and
|
||||
+ * the latterwaits only on the "owners" member. Note then that "owners" must be
|
||||
+ * not be the first element in the structure. */
|
||||
+ short owners;
|
||||
+};
|
||||
+C_ASSERT( sizeof(struct srw_lock) == 4 );
|
||||
|
||||
/***********************************************************************
|
||||
* RtlInitializeSRWLock (NTDLL.@)
|
||||
@@ -308,11 +204,36 @@ void WINAPI RtlInitializeSRWLock( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
void WINAPI RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- if (unix_funcs->fast_RtlAcquireSRWLockExclusive( lock ) != STATUS_NOT_IMPLEMENTED)
|
||||
- return;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
+
|
||||
+ InterlockedIncrement16( &u.s->exclusive_waiters );
|
||||
|
||||
- if (srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, SRWLOCK_RES_EXCLUSIVE ))
|
||||
- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+ BOOL wait;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ old.s = *u.s;
|
||||
+ new.s = old.s;
|
||||
+
|
||||
+ if (!old.s.owners)
|
||||
+ {
|
||||
+ /* Not locked exclusive or shared. We can try to grab it. */
|
||||
+ new.s.owners = -1;
|
||||
+ --new.s.exclusive_waiters;
|
||||
+ wait = FALSE;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wait = TRUE;
|
||||
+ }
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
+
|
||||
+ if (!wait) return;
|
||||
+ RtlWaitOnAddress( &u.s->owners, &new.s.owners, sizeof(short), NULL );
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -324,34 +245,34 @@ void WINAPI RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
void WINAPI RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- unsigned int val, tmp;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
|
||||
- if (unix_funcs->fast_RtlAcquireSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED)
|
||||
- return;
|
||||
-
|
||||
- /* Acquires a shared lock. If it's currently not possible to add elements to
|
||||
- * the shared queue, then request exclusive access instead. */
|
||||
- for (val = *(unsigned int *)&lock->Ptr;; val = tmp)
|
||||
+ for (;;)
|
||||
{
|
||||
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_IN_EXCLUSIVE))
|
||||
- tmp = val + SRWLOCK_RES_EXCLUSIVE;
|
||||
- else
|
||||
- tmp = val + SRWLOCK_RES_SHARED;
|
||||
- if ((tmp = InterlockedCompareExchange( (int *)&lock->Ptr, tmp, val )) == val)
|
||||
- break;
|
||||
- }
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+ BOOL wait;
|
||||
|
||||
- /* Drop exclusive access again and instead requeue for shared access. */
|
||||
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_IN_EXCLUSIVE))
|
||||
- {
|
||||
- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
|
||||
- val = srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr, (SRWLOCK_RES_SHARED
|
||||
- - SRWLOCK_RES_EXCLUSIVE) ) - SRWLOCK_RES_EXCLUSIVE;
|
||||
- srwlock_leave_exclusive( lock, val );
|
||||
- }
|
||||
+ do
|
||||
+ {
|
||||
+ old.s = *u.s;
|
||||
+ new = old;
|
||||
+
|
||||
+ if (old.s.owners != -1 && !old.s.exclusive_waiters)
|
||||
+ {
|
||||
+ /* Not locked exclusive, and no exclusive waiters.
|
||||
+ * We can try to grab it. */
|
||||
+ ++new.s.owners;
|
||||
+ wait = FALSE;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wait = TRUE;
|
||||
+ }
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
|
||||
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
|
||||
- NtWaitForKeyedEvent( 0, srwlock_key_shared(lock), FALSE, NULL );
|
||||
+ if (!wait) return;
|
||||
+ RtlWaitOnAddress( u.s, &new.s, sizeof(struct srw_lock), NULL );
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -359,11 +280,23 @@ void WINAPI RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
void WINAPI RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- if (unix_funcs->fast_RtlReleaseSRWLockExclusive( lock ) != STATUS_NOT_IMPLEMENTED)
|
||||
- return;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ old.s = *u.s;
|
||||
+ new = old;
|
||||
+
|
||||
+ if (old.s.owners != -1) ERR("Lock %p is not owned exclusive!\n", lock);
|
||||
|
||||
- srwlock_leave_exclusive( lock, srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr,
|
||||
- - SRWLOCK_RES_EXCLUSIVE ) - SRWLOCK_RES_EXCLUSIVE );
|
||||
+ new.s.owners = 0;
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
+
|
||||
+ if (new.s.exclusive_waiters)
|
||||
+ RtlWakeAddressSingle( &u.s->owners );
|
||||
+ else
|
||||
+ RtlWakeAddressAll( u.s );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -371,11 +304,22 @@ void WINAPI RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
void WINAPI RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- if (unix_funcs->fast_RtlReleaseSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED)
|
||||
- return;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ old.s = *u.s;
|
||||
+ new = old;
|
||||
+
|
||||
+ if (old.s.owners == -1) ERR("Lock %p is owned exclusive!\n", lock);
|
||||
+ else if (!old.s.owners) ERR("Lock %p is not owned shared!\n", lock);
|
||||
|
||||
- srwlock_leave_shared( lock, srwlock_lock_exclusive( (unsigned int *)&lock->Ptr,
|
||||
- - SRWLOCK_RES_SHARED ) - SRWLOCK_RES_SHARED );
|
||||
+ --new.s.owners;
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
+
|
||||
+ if (!new.s.owners)
|
||||
+ RtlWakeAddressSingle( &u.s->owners );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -387,13 +331,28 @@ void WINAPI RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- NTSTATUS ret;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+ BOOLEAN ret;
|
||||
|
||||
- if ((ret = unix_funcs->fast_RtlTryAcquireSRWLockExclusive( lock )) != STATUS_NOT_IMPLEMENTED)
|
||||
- return (ret == STATUS_SUCCESS);
|
||||
+ do
|
||||
+ {
|
||||
+ old.s = *u.s;
|
||||
+ new.s = old.s;
|
||||
|
||||
- return InterlockedCompareExchange( (int *)&lock->Ptr, SRWLOCK_MASK_IN_EXCLUSIVE |
|
||||
- SRWLOCK_RES_EXCLUSIVE, 0 ) == 0;
|
||||
+ if (!old.s.owners)
|
||||
+ {
|
||||
+ /* Not locked exclusive or shared. We can try to grab it. */
|
||||
+ new.s.owners = -1;
|
||||
+ ret = TRUE;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ret = FALSE;
|
||||
+ }
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -401,20 +360,29 @@ BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
*/
|
||||
BOOLEAN WINAPI RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
{
|
||||
- unsigned int val, tmp;
|
||||
- NTSTATUS ret;
|
||||
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
|
||||
+ union { struct srw_lock s; LONG l; } old, new;
|
||||
+ BOOLEAN ret;
|
||||
|
||||
- if ((ret = unix_funcs->fast_RtlTryAcquireSRWLockShared( lock )) != STATUS_NOT_IMPLEMENTED)
|
||||
- return (ret == STATUS_SUCCESS);
|
||||
-
|
||||
- for (val = *(unsigned int *)&lock->Ptr;; val = tmp)
|
||||
+ do
|
||||
{
|
||||
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
|
||||
- return FALSE;
|
||||
- if ((tmp = InterlockedCompareExchange( (int *)&lock->Ptr, val + SRWLOCK_RES_SHARED, val )) == val)
|
||||
- break;
|
||||
- }
|
||||
- return TRUE;
|
||||
+ old.s = *u.s;
|
||||
+ new.s = old.s;
|
||||
+
|
||||
+ if (old.s.owners != -1 && !old.s.exclusive_waiters)
|
||||
+ {
|
||||
+ /* Not locked exclusive, and no exclusive waiters.
|
||||
+ * We can try to grab it. */
|
||||
+ ++new.s.owners;
|
||||
+ ret = TRUE;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ret = FALSE;
|
||||
+ }
|
||||
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
|
||||
index 1633aeb97eb..8a30e6fc749 100644
|
||||
--- a/dlls/ntdll/unix/loader.c
|
||||
+++ b/dlls/ntdll/unix/loader.c
|
||||
@@ -1511,12 +1511,6 @@ static struct unix_funcs unix_funcs =
|
||||
NtCurrentTeb,
|
||||
DbgUiIssueRemoteBreakin,
|
||||
RtlGetSystemTimePrecise,
|
||||
- fast_RtlTryAcquireSRWLockExclusive,
|
||||
- fast_RtlAcquireSRWLockExclusive,
|
||||
- fast_RtlTryAcquireSRWLockShared,
|
||||
- fast_RtlAcquireSRWLockShared,
|
||||
- fast_RtlReleaseSRWLockExclusive,
|
||||
- fast_RtlReleaseSRWLockShared,
|
||||
ntdll_atan,
|
||||
ntdll_ceil,
|
||||
ntdll_cos,
|
||||
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
|
||||
index 3645c9f9549..c32b62f9e0a 100644
|
||||
--- a/dlls/ntdll/unix/sync.c
|
||||
+++ b/dlls/ntdll/unix/sync.c
|
||||
@@ -114,8 +114,6 @@ static inline ULONGLONG monotonic_counter(void)
|
||||
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
-#define FUTEX_WAIT_BITSET 9
|
||||
-#define FUTEX_WAKE_BITSET 10
|
||||
|
||||
static int futex_private = 128;
|
||||
|
||||
@@ -129,16 +127,6 @@ static inline int futex_wake( const int *addr, int val )
|
||||
return syscall( __NR_futex, addr, FUTEX_WAKE | futex_private, val, NULL, 0, 0 );
|
||||
}
|
||||
|
||||
-static inline int futex_wait_bitset( const int *addr, int val, struct timespec *timeout, int mask )
|
||||
-{
|
||||
- return syscall( __NR_futex, addr, FUTEX_WAIT_BITSET | futex_private, val, timeout, 0, mask );
|
||||
-}
|
||||
-
|
||||
-static inline int futex_wake_bitset( const int *addr, int val, int mask )
|
||||
-{
|
||||
- return syscall( __NR_futex, addr, FUTEX_WAKE_BITSET | futex_private, val, NULL, 0, mask );
|
||||
-}
|
||||
-
|
||||
static inline int use_futexes(void)
|
||||
{
|
||||
static int supported = -1;
|
||||
@@ -156,16 +144,6 @@ static inline int use_futexes(void)
|
||||
return supported;
|
||||
}
|
||||
|
||||
-static int *get_futex(void **ptr)
|
||||
-{
|
||||
- if (sizeof(void *) == 8)
|
||||
- return (int *)((((ULONG_PTR)ptr) + 3) & ~3);
|
||||
- else if (!(((ULONG_PTR)ptr) & 3))
|
||||
- return (int *)ptr;
|
||||
- else
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2232,290 +2210,3 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||
return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout );
|
||||
#endif
|
||||
}
|
||||
-
|
||||
-
|
||||
-#ifdef __linux__
|
||||
-
|
||||
-/* Futex-based SRW lock implementation:
|
||||
- *
|
||||
- * Since we can rely on the kernel to release all threads and don't need to
|
||||
- * worry about NtReleaseKeyedEvent(), we can simplify the layout a bit. The
|
||||
- * layout looks like this:
|
||||
- *
|
||||
- * 31 - Exclusive lock bit, set if the resource is owned exclusively.
|
||||
- * 30-16 - Number of exclusive waiters. Unlike the fallback implementation,
|
||||
- * this does not include the thread owning the lock, or shared threads
|
||||
- * waiting on the lock.
|
||||
- * 15 - Does this lock have any shared waiters? We use this as an
|
||||
- * optimization to avoid unnecessary FUTEX_WAKE_BITSET calls when
|
||||
- * releasing an exclusive lock.
|
||||
- * 14-0 - Number of shared owners. Unlike the fallback implementation, this
|
||||
- * does not include the number of shared threads waiting on the lock.
|
||||
- * Thus the state [1, x, >=1] will never occur.
|
||||
- */
|
||||
-
|
||||
-#define SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT 0x80000000
|
||||
-#define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK 0x7fff0000
|
||||
-#define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC 0x00010000
|
||||
-#define SRWLOCK_FUTEX_SHARED_WAITERS_BIT 0x00008000
|
||||
-#define SRWLOCK_FUTEX_SHARED_OWNERS_MASK 0x00007fff
|
||||
-#define SRWLOCK_FUTEX_SHARED_OWNERS_INC 0x00000001
|
||||
-
|
||||
-/* Futex bitmasks; these are independent from the bits in the lock itself. */
|
||||
-#define SRWLOCK_FUTEX_BITSET_EXCLUSIVE 1
|
||||
-#define SRWLOCK_FUTEX_BITSET_SHARED 2
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int old, new, *futex;
|
||||
- NTSTATUS ret;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
|
||||
- && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
|
||||
- {
|
||||
- /* Not locked exclusive or shared. We can try to grab it. */
|
||||
- new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
|
||||
- ret = STATUS_SUCCESS;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- new = old;
|
||||
- ret = STATUS_TIMEOUT;
|
||||
- }
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int old, new, *futex;
|
||||
- BOOLEAN wait;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- /* Atomically increment the exclusive waiter count. */
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
- new = old + SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
|
||||
- assert(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- for (;;)
|
||||
- {
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
|
||||
- && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
|
||||
- {
|
||||
- /* Not locked exclusive or shared. We can try to grab it. */
|
||||
- new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
|
||||
- assert(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
|
||||
- new -= SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
|
||||
- wait = FALSE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- new = old;
|
||||
- wait = TRUE;
|
||||
- }
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- if (!wait)
|
||||
- return STATUS_SUCCESS;
|
||||
-
|
||||
- futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
|
||||
- }
|
||||
-
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int new, old, *futex;
|
||||
- NTSTATUS ret;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
|
||||
- && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
|
||||
- {
|
||||
- /* Not locked exclusive, and no exclusive waiters. We can try to
|
||||
- * grab it. */
|
||||
- new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
|
||||
- assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
|
||||
- ret = STATUS_SUCCESS;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- new = old;
|
||||
- ret = STATUS_TIMEOUT;
|
||||
- }
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int old, new, *futex;
|
||||
- BOOLEAN wait;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- for (;;)
|
||||
- {
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
|
||||
- && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
|
||||
- {
|
||||
- /* Not locked exclusive, and no exclusive waiters. We can try
|
||||
- * to grab it. */
|
||||
- new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
|
||||
- assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
|
||||
- wait = FALSE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- new = old | SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
|
||||
- wait = TRUE;
|
||||
- }
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- if (!wait)
|
||||
- return STATUS_SUCCESS;
|
||||
-
|
||||
- futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_SHARED );
|
||||
- }
|
||||
-
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int old, new, *futex;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT))
|
||||
- {
|
||||
- ERR("Lock %p is not owned exclusive! (%#x)\n", lock, *futex);
|
||||
- return STATUS_RESOURCE_NOT_OWNED;
|
||||
- }
|
||||
-
|
||||
- new = old & ~SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
|
||||
-
|
||||
- if (!(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
|
||||
- new &= ~SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- if (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)
|
||||
- futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
|
||||
- else if (old & SRWLOCK_FUTEX_SHARED_WAITERS_BIT)
|
||||
- futex_wake_bitset( futex, INT_MAX, SRWLOCK_FUTEX_BITSET_SHARED );
|
||||
-
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- int old, new, *futex;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &lock->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- do
|
||||
- {
|
||||
- old = *futex;
|
||||
-
|
||||
- if (old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
|
||||
- {
|
||||
- ERR("Lock %p is owned exclusive! (%#x)\n", lock, *futex);
|
||||
- return STATUS_RESOURCE_NOT_OWNED;
|
||||
- }
|
||||
- else if (!(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
|
||||
- {
|
||||
- ERR("Lock %p is not owned shared! (%#x)\n", lock, *futex);
|
||||
- return STATUS_RESOURCE_NOT_OWNED;
|
||||
- }
|
||||
-
|
||||
- new = old - SRWLOCK_FUTEX_SHARED_OWNERS_INC;
|
||||
- } while (InterlockedCompareExchange( futex, new, old ) != old);
|
||||
-
|
||||
- /* Optimization: only bother waking if there are actually exclusive waiters. */
|
||||
- if (!(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK) && (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
|
||||
- futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
|
||||
-
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 4462c3ad218..fe6813551e2 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -93,12 +93,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON
|
||||
extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
|
||||
extern LONGLONG CDECL fast_RtlGetSystemTimePrecise(void) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *size ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
|
||||
index 6116f408572..5ffb09ce397 100644
|
||||
--- a/dlls/ntdll/unixlib.h
|
||||
+++ b/dlls/ntdll/unixlib.h
|
||||
@@ -38,14 +38,6 @@ struct unix_funcs
|
||||
NTSTATUS (WINAPI *DbgUiIssueRemoteBreakin)( HANDLE process );
|
||||
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
|
||||
|
||||
- /* fast locks */
|
||||
- NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||
- NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock );
|
||||
-
|
||||
/* math functions */
|
||||
double (CDECL *atan)( double d );
|
||||
double (CDECL *ceil)( double d );
|
||||
diff --git a/include/winbase.h b/include/winbase.h
|
||||
index dc8aa081be4..2ebcb3e735a 100644
|
||||
--- a/include/winbase.h
|
||||
+++ b/include/winbase.h
|
||||
@@ -2928,14 +2928,18 @@ extern WCHAR * CDECL wine_get_dos_file_name( LPCSTR str );
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
#pragma intrinsic(_InterlockedIncrement)
|
||||
+#pragma intrinsic(_InterlockedIncrement16)
|
||||
#pragma intrinsic(_InterlockedDecrement)
|
||||
+#pragma intrinsic(_InterlockedDecrement16)
|
||||
|
||||
long _InterlockedCompareExchange(long volatile*,long,long);
|
||||
long long _InterlockedCompareExchange64(long long volatile*,long long,long long);
|
||||
long _InterlockedDecrement(long volatile*);
|
||||
+short _InterlockedDecrement16(short volatile*);
|
||||
long _InterlockedExchange(long volatile*,long);
|
||||
long _InterlockedExchangeAdd(long volatile*,long);
|
||||
long _InterlockedIncrement(long volatile*);
|
||||
+short _InterlockedIncrement16(short volatile *);
|
||||
|
||||
static FORCEINLINE LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
|
||||
{
|
||||
@@ -2962,11 +2966,21 @@ static FORCEINLINE LONG WINAPI InterlockedIncrement( LONG volatile *dest )
|
||||
return _InterlockedIncrement( (long volatile *)dest );
|
||||
}
|
||||
|
||||
+static FORCEINLINE short WINAPI InterlockedIncrement16( short volatile *dest )
|
||||
+{
|
||||
+ return _InterlockedIncrement16( (short volatile *)dest );
|
||||
+}
|
||||
+
|
||||
static FORCEINLINE LONG WINAPI InterlockedDecrement( LONG volatile *dest )
|
||||
{
|
||||
return _InterlockedDecrement( (long volatile *)dest );
|
||||
}
|
||||
|
||||
+static FORCEINLINE short WINAPI InterlockedDecrement16( short volatile *dest )
|
||||
+{
|
||||
+ return _InterlockedDecrement16( (short volatile *)dest );
|
||||
+}
|
||||
+
|
||||
#ifndef __i386__
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer)
|
||||
@@ -3031,11 +3045,21 @@ static FORCEINLINE LONG WINAPI InterlockedIncrement( LONG volatile *dest )
|
||||
return __sync_add_and_fetch( dest, 1 );
|
||||
}
|
||||
|
||||
+static FORCEINLINE short WINAPI InterlockedIncrement16( short volatile *dest )
|
||||
+{
|
||||
+ return __sync_add_and_fetch( dest, 1 );
|
||||
+}
|
||||
+
|
||||
static FORCEINLINE LONG WINAPI InterlockedDecrement( LONG volatile *dest )
|
||||
{
|
||||
return __sync_add_and_fetch( dest, -1 );
|
||||
}
|
||||
|
||||
+static FORCEINLINE short WINAPI InterlockedDecrement16( short volatile *dest )
|
||||
+{
|
||||
+ return __sync_add_and_fetch( dest, -1 );
|
||||
+}
|
||||
+
|
||||
static FORCEINLINE PVOID WINAPI InterlockedExchangePointer( PVOID volatile *dest, PVOID val )
|
||||
{
|
||||
PVOID ret;
|
||||
--
|
||||
2.29.2
|
||||
|
2
patches/ntdll-NtAlertThreadByThreadId/definition
Normal file
2
patches/ntdll-NtAlertThreadByThreadId/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [50292] Process-local synchronization objects use private interfaces into the Unix library
|
||||
Depends: server-Object_Types
|
@ -169,6 +169,7 @@ patch_enable_all ()
|
||||
enable_ntdll_Junction_Points="$1"
|
||||
enable_ntdll_Manifest_Range="$1"
|
||||
enable_ntdll_NtAccessCheck="$1"
|
||||
enable_ntdll_NtAlertThreadByThreadId="$1"
|
||||
enable_ntdll_NtDevicePath="$1"
|
||||
enable_ntdll_NtQueryEaFile="$1"
|
||||
enable_ntdll_NtQuerySection="$1"
|
||||
@ -589,6 +590,9 @@ patch_enable ()
|
||||
ntdll-NtAccessCheck)
|
||||
enable_ntdll_NtAccessCheck="$2"
|
||||
;;
|
||||
ntdll-NtAlertThreadByThreadId)
|
||||
enable_ntdll_NtAlertThreadByThreadId="$2"
|
||||
;;
|
||||
ntdll-NtDevicePath)
|
||||
enable_ntdll_NtDevicePath="$2"
|
||||
;;
|
||||
@ -1561,6 +1565,13 @@ if test "$enable_ntdll_NtDevicePath" -eq 1; then
|
||||
enable_ntdll_Pipe_SpecialCharacters=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_Dealloc_Thread_Stack" -eq 1; then
|
||||
if test "$enable_ntdll_NtAlertThreadByThreadId" -gt 1; then
|
||||
abort "Patchset ntdll-NtAlertThreadByThreadId disabled, but ntdll-Dealloc_Thread_Stack depends on that."
|
||||
fi
|
||||
enable_ntdll_NtAlertThreadByThreadId=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_Builtin_Prot" -eq 1; then
|
||||
if test "$enable_ntdll_WRITECOPY" -gt 1; then
|
||||
abort "Patchset ntdll-WRITECOPY disabled, but ntdll-Builtin_Prot depends on that."
|
||||
@ -1661,6 +1672,20 @@ if test "$enable_nvapi_Stub_DLL" -eq 1; then
|
||||
enable_nvcuda_CUDA_Support=1
|
||||
fi
|
||||
|
||||
if test "$enable_Staging" -eq 1; then
|
||||
if test "$enable_ntdll_NtAlertThreadByThreadId" -gt 1; then
|
||||
abort "Patchset ntdll-NtAlertThreadByThreadId disabled, but Staging depends on that."
|
||||
fi
|
||||
enable_ntdll_NtAlertThreadByThreadId=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_NtAlertThreadByThreadId" -eq 1; then
|
||||
if test "$enable_server_Object_Types" -gt 1; then
|
||||
abort "Patchset server-Object_Types disabled, but ntdll-NtAlertThreadByThreadId depends on that."
|
||||
fi
|
||||
enable_server_Object_Types=1
|
||||
fi
|
||||
|
||||
|
||||
# Patchset Compiler_Warnings
|
||||
# |
|
||||
@ -1699,14 +1724,69 @@ if test "$enable_Pipelight" -eq 1; then
|
||||
patch_apply Pipelight/0004-winex11.drv-Indicate-direct-rendering-through-OpenGL.patch
|
||||
fi
|
||||
|
||||
# Patchset Staging
|
||||
# Patchset server-Object_Types
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#44629] Process Hacker can't enumerate handles
|
||||
# | * [#45374] Yet Another Process Monitor (.NET 2.0 app) reports System.AccessViolationException
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * Makefile.in, dlls/ntdll/Makefile.in, dlls/ntdll/loader.c
|
||||
# | * dlls/ntdll/tests/info.c, dlls/ntdll/tests/om.c, dlls/ntdll/unix/file.c, dlls/ntdll/unix/system.c, include/winternl.h,
|
||||
# | server/completion.c, server/directory.c, server/event.c, server/file.c, server/handle.c, server/mailslot.c,
|
||||
# | server/main.c, server/mapping.c, server/mutex.c, server/named_pipe.c, server/object.c, server/object.h,
|
||||
# | server/process.c, server/protocol.def, server/registry.c, server/semaphore.c, server/symlink.c, server/thread.c,
|
||||
# | server/timer.c, server/token.c, server/winstation.c
|
||||
# |
|
||||
if test "$enable_server_Object_Types" -eq 1; then
|
||||
patch_apply server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch
|
||||
patch_apply server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch
|
||||
patch_apply server-Object_Types/0003-server-Register-types-during-startup.patch
|
||||
patch_apply server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch
|
||||
patch_apply server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch
|
||||
patch_apply server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch
|
||||
patch_apply server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch
|
||||
fi
|
||||
|
||||
# Patchset ntdll-NtAlertThreadByThreadId
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * server-Object_Types
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#50292] Process-local synchronization objects use private interfaces into the Unix library
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/Makefile.in, dlls/ntdll/critsection.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll.spec, dlls/ntdll/ntdll_misc.h,
|
||||
# | dlls/ntdll/sync.c, dlls/ntdll/tests/Makefile.in, dlls/ntdll/tests/om.c, dlls/ntdll/tests/sync.c,
|
||||
# | dlls/ntdll/unix/loader.c, dlls/ntdll/unix/sync.c, dlls/ntdll/unix/thread.c, dlls/ntdll/unix/unix_private.h,
|
||||
# | dlls/ntdll/unix/virtual.c, dlls/ntdll/unixlib.h, include/winbase.h, include/winternl.h
|
||||
# |
|
||||
if test "$enable_ntdll_NtAlertThreadByThreadId" -eq 1; then
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0008-ntdll-Use-a-separate-lock-to-access-the-PE-TEB-list.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0010-ntdll-Merge-critsection.c-into-sync.c.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch
|
||||
fi
|
||||
|
||||
# Patchset Staging
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * server-Object_Types, ntdll-NtAlertThreadByThreadId
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/loader.c
|
||||
# |
|
||||
if test "$enable_Staging" -eq 1; then
|
||||
patch_apply Staging/0001-kernel32-Add-winediag-message-to-show-warning-that-t.patch
|
||||
patch_apply Staging/0002-winelib-Append-Staging-at-the-end-of-the-version-s.patch
|
||||
fi
|
||||
|
||||
# Patchset advapi32-LsaLookupPrivilegeName
|
||||
@ -3029,6 +3109,9 @@ fi
|
||||
|
||||
# Patchset ntdll-Dealloc_Thread_Stack
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * server-Object_Types, ntdll-NtAlertThreadByThreadId
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/unix/unix_private.h, dlls/ntdll/unix/virtual.c
|
||||
# |
|
||||
@ -3579,29 +3662,6 @@ if test "$enable_server_Key_State" -eq 1; then
|
||||
patch_apply server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch
|
||||
fi
|
||||
|
||||
# Patchset server-Object_Types
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#44629] Process Hacker can't enumerate handles
|
||||
# | * [#45374] Yet Another Process Monitor (.NET 2.0 app) reports System.AccessViolationException
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/tests/info.c, dlls/ntdll/tests/om.c, dlls/ntdll/unix/file.c, dlls/ntdll/unix/system.c, include/winternl.h,
|
||||
# | server/completion.c, server/directory.c, server/event.c, server/file.c, server/handle.c, server/mailslot.c,
|
||||
# | server/main.c, server/mapping.c, server/mutex.c, server/named_pipe.c, server/object.c, server/object.h,
|
||||
# | server/process.c, server/protocol.def, server/registry.c, server/semaphore.c, server/symlink.c, server/thread.c,
|
||||
# | server/timer.c, server/token.c, server/winstation.c
|
||||
# |
|
||||
if test "$enable_server_Object_Types" -eq 1; then
|
||||
patch_apply server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch
|
||||
patch_apply server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch
|
||||
patch_apply server-Object_Types/0003-server-Register-types-during-startup.patch
|
||||
patch_apply server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch
|
||||
patch_apply server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch
|
||||
patch_apply server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch
|
||||
patch_apply server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch
|
||||
fi
|
||||
|
||||
# Patchset server-Registry_Notifications
|
||||
# |
|
||||
# | Modified files:
|
||||
|
Loading…
Reference in New Issue
Block a user