mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Rebase against 80a30625a70343cf6f38d80d02f640d684e27e6d.
This commit is contained in:
parent
9a5667dba1
commit
5f113860f5
File diff suppressed because it is too large
Load Diff
@ -1,209 +0,0 @@
|
||||
From 2cecfc6394a63db07b92c572d0702cf2a8bf0f31 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] ntdll/tests: Add some tests for Rtl* resources.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/sync.c | 164 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 164 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
|
||||
index 3d6b6a3a04d..21124dae922 100644
|
||||
--- a/dlls/ntdll/tests/sync.c
|
||||
+++ b/dlls/ntdll/tests/sync.c
|
||||
@@ -44,7 +44,12 @@ static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * );
|
||||
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 * );
|
||||
@@ -595,6 +600,159 @@ static void test_wait_on_address(void)
|
||||
ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
|
||||
}
|
||||
|
||||
+static 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");
|
||||
@@ -617,7 +775,12 @@ START_TEST(sync)
|
||||
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");
|
||||
@@ -627,4 +790,5 @@ START_TEST(sync)
|
||||
test_mutant();
|
||||
test_semaphore();
|
||||
test_keyed_events();
|
||||
+ test_resource();
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 41d56b3e16cbe1dd59b19eee9faf0d6b3ec9bf8f Mon Sep 17 00:00:00 2001
|
||||
From c83cd4d1151d182c3ae35f87b20b6ba30cf24316 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 7 Jun 2021 16:26:18 -0500
|
||||
Subject: [PATCH] ntdll: Reimplement Win32 futexes on top of thread-ID alerts.
|
||||
@ -6,34 +6,36 @@ Subject: [PATCH] ntdll: Reimplement Win32 futexes on top of thread-ID alerts.
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
|
||||
---
|
||||
dlls/ntdll/sync.c | 215 ++++++++++++++++++++++++++++++++++++++-
|
||||
dlls/ntdll/sync.c | 214 ++++++++++++++++++++++++++++++++++++++-
|
||||
dlls/ntdll/unix/loader.c | 3 -
|
||||
dlls/ntdll/unix/sync.c | 162 -----------------------------
|
||||
dlls/ntdll/unixlib.h | 6 +-
|
||||
4 files changed, 213 insertions(+), 173 deletions(-)
|
||||
4 files changed, 212 insertions(+), 173 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index f1263ae33fd..c0a6e3a729e 100644
|
||||
index bfb30661864..db68a466d8a 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -34,8 +34,16 @@
|
||||
@@ -34,11 +34,18 @@
|
||||
#include "windef.h"
|
||||
#include "winternl.h"
|
||||
#include "wine/debug.h"
|
||||
+#include "wine/list.h"
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
+
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
+static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
|
||||
+{
|
||||
+ if (!timeout) return "(infinite)";
|
||||
+ return wine_dbgstr_longlong( timeout->QuadPart );
|
||||
+}
|
||||
|
||||
+
|
||||
/******************************************************************
|
||||
* RtlRunOnceInitialize (NTDLL.@)
|
||||
@@ -530,13 +538,142 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||
*/
|
||||
@@ -863,13 +870,142 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -177,7 +179,7 @@ index f1263ae33fd..c0a6e3a729e 100644
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -544,7 +681,42 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||
@@ -877,7 +1013,42 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||
*/
|
||||
void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
{
|
||||
@ -221,7 +223,7 @@ index f1263ae33fd..c0a6e3a729e 100644
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -552,5 +724,42 @@ void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
@@ -885,5 +1056,42 @@ void WINAPI RtlWakeAddressAll( const void *addr )
|
||||
*/
|
||||
void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||
{
|
||||
|
@ -1,937 +0,0 @@
|
||||
From daa52c29f5fe2ba16338672bc545259d3314295c 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] ntdll: Merge critsection.c into sync.c.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
Signed-off-by: Zebediah Figura <zfigura@codeweavers.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 aac7f8eead7..29b772c7c56 100644
|
||||
--- a/dlls/ntdll/Makefile.in
|
||||
+++ b/dlls/ntdll/Makefile.in
|
||||
@@ -11,7 +11,6 @@ EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7bc00000
|
||||
C_SRCS = \
|
||||
actctx.c \
|
||||
atom.c \
|
||||
- critsection.c \
|
||||
crypt.c \
|
||||
debugbuffer.c \
|
||||
env.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 c0a6e3a729e..db68a466d8a 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 )
|
||||
{
|
||||
@@ -141,6 +142,337 @@ DWORD WINAPI RtlRunOnceComplete( RTL_RUN_ONCE *once, ULONG flags, void *context
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * 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;
|
||||
+}
|
||||
+
|
||||
/******************************************************************
|
||||
* RtlRunOnceExecuteOnce (NTDLL.@)
|
||||
*/
|
||||
--
|
||||
2.33.0
|
||||
|
@ -51,7 +51,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "e73bb07ff59d0d0b7925df3d642299689275b0a8"
|
||||
echo "80a30625a70343cf6f38d80d02f640d684e27e6d"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
@ -2455,20 +2455,15 @@ fi
|
||||
# | * [#50292] Process-local synchronization objects use private interfaces into the Unix library
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/Makefile.in, dlls/ntdll/critsection.c, dlls/ntdll/ntdll.spec, 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/unix_private.h, dlls/ntdll/unixlib.h, dlls/wow64/sync.c, dlls/wow64/syscall.h,
|
||||
# | include/winternl.h
|
||||
# | * dlls/ntdll/ntdll.spec, dlls/ntdll/sync.c, dlls/ntdll/tests/sync.c, dlls/ntdll/unix/loader.c, dlls/ntdll/unix/sync.c,
|
||||
# | dlls/ntdll/unix/unix_private.h, dlls/ntdll/unixlib.h, dlls/wow64/sync.c, dlls/wow64/syscall.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-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0008-ntdll-Merge-critsection.c-into-sync.c.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch
|
||||
patch_apply ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch
|
||||
|
@ -1 +1 @@
|
||||
e73bb07ff59d0d0b7925df3d642299689275b0a8
|
||||
80a30625a70343cf6f38d80d02f640d684e27e6d
|
||||
|
Loading…
Reference in New Issue
Block a user