Rebase against 80a30625a70343cf6f38d80d02f640d684e27e6d.

This commit is contained in:
Zebediah Figura 2021-10-27 17:05:11 -05:00
parent 9a5667dba1
commit 5f113860f5
6 changed files with 17 additions and 2481 deletions

View File

@ -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

View File

@ -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 )
{

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
e73bb07ff59d0d0b7925df3d642299689275b0a8
80a30625a70343cf6f38d80d02f640d684e27e6d