Rebase against 32fb017d4a22be38ca271bf387e466e958601355.

This commit is contained in:
Zebediah Figura 2021-11-18 18:07:35 -06:00
parent 7e42d0ac1a
commit d3d93cfa0d
9 changed files with 9 additions and 1927 deletions

View File

@ -1,149 +0,0 @@
From a05cafc7633a48989edd89fc99bc5d63ecd2f3bd Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 30 Apr 2021 16:43:08 -0500
Subject: [PATCH] ntdll: Implement thread-ID alerts using Mach semaphores on
Mac.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
---
dlls/ntdll/unix/sync.c | 75 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 058262ac0ad..48960b5cb83 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -2288,10 +2288,14 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
union tid_alert_entry
{
+#ifdef __APPLE__
+ semaphore_t sem;
+#else
HANDLE event;
#ifdef __linux__
int futex;
#endif
+#endif
};
#define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry))
@@ -2326,6 +2330,17 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid )
entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE];
+#ifdef __APPLE__
+ if (!entry->sem)
+ {
+ semaphore_t sem;
+
+ if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 ))
+ return NULL;
+ if (InterlockedCompareExchange( (int *)&entry->sem, sem, NULL ))
+ semaphore_destroy( mach_task_self(), sem );
+ }
+#else
#ifdef __linux__
if (use_futexes())
return entry;
@@ -2340,6 +2355,7 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid )
if (InterlockedCompareExchangePointer( &entry->event, event, NULL ))
NtClose( event );
}
+#endif
return entry;
}
@@ -2356,6 +2372,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
if (!entry) return STATUS_INVALID_CID;
+#ifdef __APPLE__
+ semaphore_signal( entry->sem );
+ return STATUS_SUCCESS;
+#else
#ifdef __linux__
if (use_futexes())
{
@@ -2367,10 +2387,11 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
#endif
return NtSetEvent( entry->event, NULL );
+#endif
}
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
static LONGLONG get_absolute_timeout( const LARGE_INTEGER *timeout )
{
LARGE_INTEGER now;
@@ -2393,6 +2414,57 @@ static LONGLONG update_timeout( ULONGLONG end )
#endif
+#ifdef __APPLE__
+
+/***********************************************************************
+ * NtWaitForAlertByThreadId (NTDLL.@)
+ */
+NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout )
+{
+ union tid_alert_entry *entry = get_tid_alert_entry( NtCurrentTeb()->ClientId.UniqueThread );
+ semaphore_t sem;
+ ULONGLONG end;
+ kern_return_t ret;
+
+ TRACE( "%p %s\n", address, debugstr_timeout( timeout ) );
+
+ if (!entry) return STATUS_INVALID_CID;
+ sem = entry->sem;
+
+ if (timeout)
+ {
+ if (timeout->QuadPart == TIMEOUT_INFINITE)
+ timeout = NULL;
+ else
+ end = get_absolute_timeout( timeout );
+ }
+
+ for (;;)
+ {
+ if (timeout)
+ {
+ LONGLONG timeleft = update_timeout( end );
+ mach_timespec_t timespec;
+
+ timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
+ timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100;
+ ret = semaphore_timedwait( sem, timespec );
+ }
+ else
+ ret = semaphore_wait( sem );
+
+ switch (ret)
+ {
+ case KERN_SUCCESS: return STATUS_ALERTED;
+ case KERN_ABORTED: continue;
+ case KERN_OPERATION_TIMED_OUT: return STATUS_TIMEOUT;
+ default: return STATUS_INVALID_HANDLE;
+ }
+ }
+}
+
+#else
+
/***********************************************************************
* NtWaitForAlertByThreadId (NTDLL.@)
*/
@@ -2445,6 +2517,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
return status;
}
+#endif
#ifdef __linux__
--
2.30.2

View File

@ -1,461 +0,0 @@
From 4b2ad3bf49e77c6cb0e541329ac851d054e6f649 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.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
---
dlls/ntdll/sync.c | 173 ++++++++++++++++++++++++++++++++++++++-
dlls/ntdll/unix/loader.c | 3 -
dlls/ntdll/unix/sync.c | 162 ------------------------------------
dlls/ntdll/unixlib.h | 6 +-
4 files changed, 171 insertions(+), 173 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index bfb30661864..adc03c9ff7a 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -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_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.@)
*/
@@ -863,13 +870,111 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
return status;
}
+/* RtlWaitOnAddress() and RtlWakeAddress*(), hereafter referred to as "Win32
+ * futexes", offer futex-like semantics with a variable set of address sizes,
+ * but are limited to a single process. They are also fair—the documentation
+ * specifies this, and tests bear it out.
+ *
+ * On Windows they are implemented using NtAlertThreadByThreadId and
+ * NtWaitForAlertByThreadId, which manipulate a single flag (similar to a
+ * manual-reset event) per thread. This can be tested by attempting to wake a
+ * thread waiting in RtlWaitOnAddress() via NtAlertThreadByThreadId.
+ */
+
+struct futex_entry
+{
+ struct list entry;
+ const void *addr;
+ DWORD tid;
+};
+
+struct futex_queue
+{
+ struct list queue;
+ LONG lock;
+};
+
+static struct futex_queue futex_queues[256];
+
+static struct futex_queue *get_futex_queue( const void *addr )
+{
+ ULONG_PTR val = (ULONG_PTR)addr;
+
+ return &futex_queues[(val >> 4) % ARRAY_SIZE(futex_queues)];
+}
+
+static void spin_wrlock( LONG *lock )
+{
+ while (InterlockedCompareExchange( lock, -1, 0 ))
+ YieldProcessor();
+}
+
+static void spin_wrunlock( LONG *lock )
+{
+ InterlockedExchange( lock, 0 );
+}
+
+static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
+{
+ switch (size)
+ {
+ case 1:
+ return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
+ case 2:
+ return (*(const USHORT *)addr == *(const USHORT *)cmp);
+ case 4:
+ return (*(const ULONG *)addr == *(const ULONG *)cmp);
+ case 8:
+ return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
+ }
+
+ return FALSE;
+}
+
/***********************************************************************
* RtlWaitOnAddress (NTDLL.@)
*/
NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
const LARGE_INTEGER *timeout )
{
- return unix_funcs->RtlWaitOnAddress( addr, cmp, size, timeout );
+ struct futex_queue *queue = get_futex_queue( addr );
+ struct futex_entry entry;
+ NTSTATUS ret;
+
+ TRACE("addr %p cmp %p size %#Ix timeout %s\n", addr, cmp, size, debugstr_timeout( timeout ));
+
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return STATUS_INVALID_PARAMETER;
+
+ entry.addr = addr;
+ entry.tid = GetCurrentThreadId();
+
+ spin_wrlock( &queue->lock );
+
+ if (!compare_addr( addr, cmp, size ))
+ {
+ spin_wrunlock( &queue->lock );
+ return STATUS_SUCCESS;
+ }
+
+ if (!queue->queue.next)
+ list_init( &queue->queue );
+ list_add_tail( &queue->queue, &entry.entry );
+
+ spin_wrunlock( &queue->lock );
+
+ ret = NtWaitForAlertByThreadId( NULL, timeout );
+
+ spin_wrlock( &queue->lock );
+ /* We may have already been removed by a call to RtlWakeAddressSingle(). */
+ if (entry.addr)
+ list_remove( &entry.entry );
+ spin_wrunlock( &queue->lock );
+
+ TRACE("returning %#x\n", ret);
+
+ if (ret == STATUS_ALERTED) ret = STATUS_SUCCESS;
+ return ret;
}
/***********************************************************************
@@ -877,7 +982,37 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
*/
void WINAPI RtlWakeAddressAll( const void *addr )
{
- return unix_funcs->RtlWakeAddressAll( addr );
+ struct futex_queue *queue = get_futex_queue( addr );
+ unsigned int count = 0, i;
+ struct futex_entry *entry;
+ DWORD tids[256];
+
+ TRACE("%p\n", addr);
+
+ if (!addr) return;
+
+ spin_wrlock( &queue->lock );
+
+ if (!queue->queue.next)
+ list_init(&queue->queue);
+
+ LIST_FOR_EACH_ENTRY( entry, &queue->queue, struct futex_entry, entry )
+ {
+ if (entry->addr == addr)
+ {
+ /* Try to buffer wakes, so that we don't make a system call while
+ * holding a spinlock. */
+ if (count < ARRAY_SIZE(tids))
+ tids[count++] = entry->tid;
+ else
+ NtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)entry->tid );
+ }
+ }
+
+ spin_wrunlock( &queue->lock );
+
+ for (i = 0; i < count; ++i)
+ NtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tids[i] );
}
/***********************************************************************
@@ -885,5 +1020,37 @@ void WINAPI RtlWakeAddressAll( const void *addr )
*/
void WINAPI RtlWakeAddressSingle( const void *addr )
{
- return unix_funcs->RtlWakeAddressSingle( addr );
+ struct futex_queue *queue = get_futex_queue( addr );
+ struct futex_entry *entry;
+ DWORD tid = 0;
+
+ TRACE("%p\n", addr);
+
+ if (!addr) return;
+
+ spin_wrlock( &queue->lock );
+
+ if (!queue->queue.next)
+ list_init(&queue->queue);
+
+ LIST_FOR_EACH_ENTRY( entry, &queue->queue, struct futex_entry, entry )
+ {
+ if (entry->addr == addr)
+ {
+ /* Try to buffer wakes, so that we don't make a system call while
+ * holding a spinlock. */
+ tid = entry->tid;
+
+ /* Remove this entry from the queue, so that a simultaneous call to
+ * RtlWakeAddressSingle() will not also wake it—two simultaneous
+ * calls must wake at least two waiters if they exist. */
+ entry->addr = NULL;
+ list_remove( &entry->entry );
+ break;
+ }
+ }
+
+ spin_wrunlock( &queue->lock );
+
+ if (tid) NtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid );
}
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index a411b01a389..59bc978022c 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -2146,9 +2146,6 @@ static struct unix_funcs unix_funcs =
NtCurrentTeb,
#endif
RtlGetSystemTimePrecise,
- RtlWaitOnAddress,
- RtlWakeAddressAll,
- RtlWakeAddressSingle,
fast_RtlpWaitForCriticalSection,
fast_RtlpUnWaitCriticalSection,
fast_RtlDeleteCriticalSection,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index ce78c11fd4b..c37dbc5e96e 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -74,10 +74,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync);
HANDLE keyed_event = 0;
-static const LARGE_INTEGER zero_timeout;
-
-static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER;
-
static const char *debugstr_timeout( const LARGE_INTEGER *timeout )
{
if (!timeout) return "(infinite)";
@@ -187,24 +183,6 @@ static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGE
#endif
-static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
-{
- switch (size)
- {
- case 1:
- return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
- case 2:
- return (*(const USHORT *)addr == *(const USHORT *)cmp);
- case 4:
- return (*(const ULONG *)addr == *(const ULONG *)cmp);
- case 8:
- return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
- }
-
- return FALSE;
-}
-
-
/* create a struct security_descriptor and contained information in one contiguous piece of memory */
NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
data_size_t *ret_len )
@@ -3035,71 +3013,6 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable,
return STATUS_SUCCESS;
}
-
-/* We can't map addresses to futex directly, because an application can wait on
- * 8 bytes, and we can't pass all 8 as the compare value to futex(). Instead we
- * map all addresses to a small fixed table of futexes. This may result in
- * spurious wakes, but the application is already expected to handle those. */
-
-static int addr_futex_table[256];
-
-static inline int *hash_addr( const void *addr )
-{
- ULONG_PTR val = (ULONG_PTR)addr;
-
- return &addr_futex_table[(val >> 2) & 255];
-}
-
-static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
- const LARGE_INTEGER *timeout )
-{
- int *futex;
- int val;
- struct timespec timespec;
- int ret;
-
- if (!use_futexes())
- return STATUS_NOT_IMPLEMENTED;
-
- futex = hash_addr( addr );
-
- /* We must read the previous value of the futex before checking the value
- * of the address being waited on. That way, if we receive a wake between
- * now and waiting on the futex, we know that val will have changed.
- * Use an atomic load so that memory accesses are ordered between this read
- * and the increment below. */
- val = InterlockedCompareExchange( futex, 0, 0 );
- if (!compare_addr( addr, cmp, size ))
- return STATUS_SUCCESS;
-
- if (timeout)
- {
- timespec_from_timeout( &timespec, timeout );
- ret = futex_wait( futex, val, &timespec );
- }
- else
- ret = futex_wait( futex, val, NULL );
-
- if (ret == -1 && errno == ETIMEDOUT)
- return STATUS_TIMEOUT;
- return STATUS_SUCCESS;
-}
-
-static inline NTSTATUS fast_wake_addr( const void *addr )
-{
- int *futex;
-
- if (!use_futexes())
- return STATUS_NOT_IMPLEMENTED;
-
- futex = hash_addr( addr );
-
- InterlockedIncrement( futex );
-
- futex_wake( futex, INT_MAX );
- return STATUS_SUCCESS;
-}
-
#else
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
@@ -3142,79 +3055,4 @@ NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value
return STATUS_NOT_IMPLEMENTED;
}
-static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T size,
- const LARGE_INTEGER *timeout )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-static inline NTSTATUS fast_wake_addr( const void *addr )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
#endif
-
-
-/***********************************************************************
- * RtlWaitOnAddress (NTDLL.@)
- */
-NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
- const LARGE_INTEGER *timeout )
-{
- select_op_t select_op;
- NTSTATUS ret;
- timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
-
- if (size != 1 && size != 2 && size != 4 && size != 8)
- return STATUS_INVALID_PARAMETER;
-
- if ((ret = fast_wait_addr( addr, cmp, size, timeout )) != STATUS_NOT_IMPLEMENTED)
- return ret;
-
- mutex_lock( &addr_mutex );
- if (!compare_addr( addr, cmp, size ))
- {
- mutex_unlock( &addr_mutex );
- return STATUS_SUCCESS;
- }
-
- if (abs_timeout < 0)
- {
- LARGE_INTEGER now;
-
- NtQueryPerformanceCounter( &now, NULL );
- abs_timeout -= now.QuadPart;
- }
-
- select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
- select_op.keyed_event.handle = wine_server_obj_handle( keyed_event );
- select_op.keyed_event.key = wine_server_client_ptr( addr );
-
- return server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE,
- abs_timeout, NULL, &addr_mutex, NULL );
-}
-
-/***********************************************************************
- * RtlWakeAddressAll (NTDLL.@)
- */
-void WINAPI RtlWakeAddressAll( const void *addr )
-{
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
-
- mutex_lock( &addr_mutex );
- while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
- mutex_unlock( &addr_mutex );
-}
-
-/***********************************************************************
- * RtlWakeAddressSingle (NTDLL.@)
- */
-void WINAPI RtlWakeAddressSingle( const void *addr )
-{
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
-
- mutex_lock( &addr_mutex );
- NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
- mutex_unlock( &addr_mutex );
-}
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index 62030d91cdb..ded05c40e17 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -26,7 +26,7 @@
struct _DISPATCHER_CONTEXT;
/* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 128
+#define NTDLL_UNIXLIB_VERSION 129
struct unix_funcs
{
@@ -37,10 +37,6 @@ struct unix_funcs
/* other Win32 API functions */
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
- NTSTATUS (WINAPI *RtlWaitOnAddress)( const void *addr, const void *cmp, SIZE_T size,
- const LARGE_INTEGER *timeout );
- void (WINAPI *RtlWakeAddressAll)( const void *addr );
- void (WINAPI *RtlWakeAddressSingle)( const void *addr );
/* fast locks */
NTSTATUS (CDECL *fast_RtlpWaitForCriticalSection)( RTL_CRITICAL_SECTION *crit, int timeout );
--
2.33.0

View File

@ -1,260 +0,0 @@
From 628256e87f979280f1251b1a90a0ac25a0469e6c Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Mon, 31 Aug 2020 23:38:09 -0500
Subject: [PATCH] ntdll: Reimplement the critical section fast path on top of
Win32 futexes.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
---
dlls/ntdll/sync.c | 35 +++++++----
dlls/ntdll/unix/loader.c | 3 -
dlls/ntdll/unix/sync.c | 109 ---------------------------------
dlls/ntdll/unix/unix_private.h | 4 --
dlls/ntdll/unixlib.h | 5 +-
5 files changed, 24 insertions(+), 132 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index db68a466d8a..3a47679bb60 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -172,19 +172,26 @@ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
{
- NTSTATUS ret;
+ LARGE_INTEGER time = {.QuadPart = timeout * (LONGLONG)-10000000};
/* debug info is cleared by MakeCriticalSectionGlobal */
- if (!crit_section_has_debuginfo( crit ) ||
- ((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
+ if (!crit_section_has_debuginfo( crit ))
{
HANDLE sem = get_semaphore( crit );
- LARGE_INTEGER time;
-
- time.QuadPart = timeout * (LONGLONG)-10000000;
- ret = NtWaitForSingleObject( sem, FALSE, &time );
+ return NtWaitForSingleObject( sem, FALSE, &time );
+ }
+ else
+ {
+ int *lock = (int *)&crit->LockSemaphore;
+ while (!InterlockedCompareExchange( lock, 0, 1 ))
+ {
+ static const int zero;
+ /* this may wait longer than specified in case of multiple wake-ups */
+ if (RtlWaitOnAddress( lock, &zero, sizeof(int), &time ) == STATUS_TIMEOUT)
+ return STATUS_TIMEOUT;
+ }
+ return STATUS_WAIT_0;
}
- return ret;
}
/******************************************************************************
@@ -274,8 +281,6 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
crit->DebugInfo = NULL;
}
- if (unix_funcs->fast_RtlDeleteCriticalSection( crit ) == STATUS_NOT_IMPLEMENTED)
- NtClose( crit->LockSemaphore );
}
else NtClose( crit->LockSemaphore );
crit->LockSemaphore = 0;
@@ -351,12 +356,18 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
- if (!crit_section_has_debuginfo( crit ) ||
- ((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
+ if (!crit_section_has_debuginfo( crit ))
{
HANDLE sem = get_semaphore( crit );
ret = NtReleaseSemaphore( sem, 1, NULL );
}
+ else
+ {
+ int *lock = (int *)&crit->LockSemaphore;
+ InterlockedExchange( lock, 1 );
+ RtlWakeAddressSingle( lock );
+ ret = STATUS_SUCCESS;
+ }
if (ret) RtlRaiseStatus( ret );
return ret;
}
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 05ae264297a..1dbcc0d7a7b 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -2145,9 +2145,6 @@ static struct unix_funcs unix_funcs =
NtCurrentTeb,
#endif
RtlGetSystemTimePrecise,
- fast_RtlpWaitForCriticalSection,
- fast_RtlpUnWaitCriticalSection,
- fast_RtlDeleteCriticalSection,
fast_RtlTryAcquireSRWLockExclusive,
fast_RtlAcquireSRWLockExclusive,
fast_RtlTryAcquireSRWLockShared,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 47a0a03b45f..12df0c90d73 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -2550,115 +2550,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
#endif
-#ifdef __linux__
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- int val;
- struct timespec timespec;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- timespec.tv_sec = timeout;
- timespec.tv_nsec = 0;
- while ((val = InterlockedCompareExchange( (int *)&crit->LockSemaphore, 0, 1 )) != 1)
- {
- /* note: this may wait longer than specified in case of signals or */
- /* multiple wake-ups, but that shouldn't be a problem */
- if (futex_wait( (int *)&crit->LockSemaphore, val, &timespec ) == -1 && errno == ETIMEDOUT)
- return STATUS_TIMEOUT;
- }
- return STATUS_WAIT_0;
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- *(int *)&crit->LockSemaphore = 1;
- futex_wake( (int *)&crit->LockSemaphore, 1 );
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
- return STATUS_SUCCESS;
-}
-
-#elif defined(__APPLE__)
-
-static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_t ret = *(int *)&crit->LockSemaphore;
- if (!ret)
- {
- semaphore_t sem;
- if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) return 0;
- if (!(ret = InterlockedCompareExchange( (int *)&crit->LockSemaphore, sem, 0 )))
- ret = sem;
- else
- semaphore_destroy( mach_task_self(), sem ); /* somebody beat us to it */
- }
- return ret;
-}
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- mach_timespec_t timespec;
- semaphore_t sem = get_mach_semaphore( crit );
-
- timespec.tv_sec = timeout;
- timespec.tv_nsec = 0;
- for (;;)
- {
- switch( semaphore_timedwait( sem, timespec ))
- {
- case KERN_SUCCESS:
- return STATUS_WAIT_0;
- case KERN_ABORTED:
- continue; /* got a signal, restart */
- case KERN_OPERATION_TIMED_OUT:
- return STATUS_TIMEOUT;
- default:
- return STATUS_INVALID_HANDLE;
- }
- }
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_t sem = get_mach_semaphore( crit );
- semaphore_signal( sem );
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_destroy( mach_task_self(), *(int *)&crit->LockSemaphore );
- return STATUS_SUCCESS;
-}
-
-#else /* __APPLE__ */
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-#endif
-
-
#ifdef __linux__
/* Futex-based SRW lock implementation:
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 641de0c465f..d44a9e128ff 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -100,10 +100,6 @@ extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PT
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
extern void (WINAPI *p__wine_ctrl_routine)(void *) DECLSPEC_HIDDEN;
extern SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock DECLSPEC_HIDDEN;
-
-extern NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index ded05c40e17..535f76a647e 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -26,7 +26,7 @@
struct _DISPATCHER_CONTEXT;
/* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 129
+#define NTDLL_UNIXLIB_VERSION 130
struct unix_funcs
{
@@ -39,9 +39,6 @@ struct unix_funcs
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
/* fast locks */
- NTSTATUS (CDECL *fast_RtlpWaitForCriticalSection)( RTL_CRITICAL_SECTION *crit, int timeout );
- NTSTATUS (CDECL *fast_RtlpUnWaitCriticalSection)( RTL_CRITICAL_SECTION *crit );
- NTSTATUS (CDECL *fast_RtlDeleteCriticalSection)( RTL_CRITICAL_SECTION *crit );
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockShared)( RTL_SRWLOCK *lock );
--
2.33.0

View File

@ -1,230 +0,0 @@
From c8044d65c40d67569c0fdbc26ce69c52b0fd3595 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Mon, 31 Aug 2020 23:55:29 -0500
Subject: [PATCH] ntdll: Get rid of the direct futex path for condition
variables.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
---
dlls/ntdll/sync.c | 24 ++++--------
dlls/ntdll/unix/loader.c | 2 -
dlls/ntdll/unix/sync.c | 71 ----------------------------------
dlls/ntdll/unix/unix_private.h | 3 --
dlls/ntdll/unixlib.h | 5 +--
5 files changed, 9 insertions(+), 96 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 3a47679bb60..6e68d07b81b 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -792,11 +792,8 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable )
*/
void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
{
- if (unix_funcs->fast_RtlWakeConditionVariable( variable, 1 ) == STATUS_NOT_IMPLEMENTED)
- {
- InterlockedIncrement( (int *)&variable->Ptr );
- RtlWakeAddressSingle( variable );
- }
+ InterlockedIncrement( (int *)&variable->Ptr );
+ RtlWakeAddressSingle( variable );
}
/***********************************************************************
@@ -806,11 +803,8 @@ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
*/
void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
{
- if (unix_funcs->fast_RtlWakeConditionVariable( variable, INT_MAX ) == STATUS_NOT_IMPLEMENTED)
- {
- InterlockedIncrement( (int *)&variable->Ptr );
- RtlWakeAddressAll( variable );
- }
+ InterlockedIncrement( (int *)&variable->Ptr );
+ RtlWakeAddressAll( variable );
}
/***********************************************************************
@@ -831,12 +825,11 @@ void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, RTL_CRITICAL_SECTION *crit,
const LARGE_INTEGER *timeout )
{
- const void *value = variable->Ptr;
+ int value = *(int *)&variable->Ptr;
NTSTATUS status;
RtlLeaveCriticalSection( crit );
- if ((status = unix_funcs->fast_wait_cv( variable, value, timeout )) == STATUS_NOT_IMPLEMENTED)
- status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
+ status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
RtlEnterCriticalSection( crit );
return status;
}
@@ -863,7 +856,7 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R
NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, RTL_SRWLOCK *lock,
const LARGE_INTEGER *timeout, ULONG flags )
{
- const void *value = variable->Ptr;
+ int value = *(int *)&variable->Ptr;
NTSTATUS status;
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
@@ -871,8 +864,7 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
else
RtlReleaseSRWLockExclusive( lock );
- if ((status = unix_funcs->fast_wait_cv( variable, value, timeout )) == STATUS_NOT_IMPLEMENTED)
- status = RtlWaitOnAddress( variable, &value, sizeof(value), timeout );
+ status = RtlWaitOnAddress( &variable->Ptr, &value, sizeof(value), timeout );
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
RtlAcquireSRWLockShared( lock );
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 1dbcc0d7a7b..32aa7267423 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -2151,8 +2151,6 @@ static struct unix_funcs unix_funcs =
fast_RtlAcquireSRWLockShared,
fast_RtlReleaseSRWLockExclusive,
fast_RtlReleaseSRWLockShared,
- fast_RtlWakeConditionVariable,
- fast_wait_cv,
load_so_dll,
init_builtin_dll,
init_unix_lib,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 12df0c90d73..7a2466f5fa3 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -162,23 +162,6 @@ static int *get_futex(void **ptr)
return NULL;
}
-static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout )
-{
- LARGE_INTEGER now;
- timeout_t diff;
-
- if (timeout->QuadPart > 0)
- {
- NtQuerySystemTime( &now );
- diff = timeout->QuadPart - now.QuadPart;
- }
- else
- diff = -timeout->QuadPart;
-
- timespec->tv_sec = diff / TICKSPERSEC;
- timespec->tv_nsec = (diff % TICKSPERSEC) * 100;
-}
-
#endif
@@ -2802,50 +2785,6 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
return STATUS_SUCCESS;
}
-NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
-{
- const char *value_ptr;
- int aligned_value, *futex;
- struct timespec timespec;
- int ret;
-
- if (!use_futexes())
- return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &variable->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- value_ptr = (const char *)&value;
- value_ptr += ((ULONG_PTR)futex) - ((ULONG_PTR)&variable->Ptr);
- aligned_value = *(int *)value_ptr;
-
- if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
- {
- timespec_from_timeout( &timespec, timeout );
- ret = futex_wait( futex, aligned_value, &timespec );
- }
- else
- ret = futex_wait( futex, aligned_value, NULL );
-
- if (ret == -1 && errno == ETIMEDOUT)
- return STATUS_TIMEOUT;
- return STATUS_WAIT_0;
-}
-
-NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
-{
- int *futex;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &variable->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- InterlockedIncrement( futex );
- futex_wake( futex, count );
- return STATUS_SUCCESS;
-}
-
#else
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
@@ -2878,14 +2817,4 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value, const LARGE_INTEGER *timeout )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
#endif
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index d44a9e128ff..61f37d4b22f 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -106,10 +106,7 @@ extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLS
extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count ) DECLSPEC_HIDDEN;
extern LONGLONG CDECL fast_RtlGetSystemTimePrecise(void) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value,
- const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispatch,
CONTEXT *context ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index 535f76a647e..a271bb05da9 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -26,7 +26,7 @@
struct _DISPATCHER_CONTEXT;
/* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 130
+#define NTDLL_UNIXLIB_VERSION 131
struct unix_funcs
{
@@ -45,9 +45,6 @@ struct unix_funcs
NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlWakeConditionVariable)( RTL_CONDITION_VARIABLE *variable, int count );
- NTSTATUS (CDECL *fast_wait_cv)( RTL_CONDITION_VARIABLE *variable, const void *value,
- const LARGE_INTEGER *timeout );
/* loader functions */
NTSTATUS (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module );
--
2.33.0

View File

@ -1,796 +0,0 @@
From 2c2b45abf167701ed4736fcc7530b9927ff67ee5 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Sun, 22 Nov 2020 20:51:10 -0600
Subject: [PATCH] ntdll: Reimplement SRW locks on top of Win32 futexes.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
---
dlls/ntdll/sync.c | 313 +++++++++++++++------------------
dlls/ntdll/unix/loader.c | 6 -
dlls/ntdll/unix/sync.c | 308 --------------------------------
dlls/ntdll/unix/unix_private.h | 6 -
dlls/ntdll/unixlib.h | 10 +-
5 files changed, 142 insertions(+), 501 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 6e68d07b81b..e380f3e4e93 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -503,127 +503,24 @@ DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN fu
return RtlRunOnceComplete( once, 0, context ? *context : NULL );
}
-
-/* SRW locks implementation
- *
- * The memory layout used by the lock is:
- *
- * 32 31 16 0
- * ________________ ________________
- * | X| #exclusive | #shared |
- * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- * Since there is no space left for a separate counter of shared access
- * threads inside the locked section the #shared field is used for multiple
- * purposes. The following table lists all possible states the lock can be
- * in, notation: [X, #exclusive, #shared]:
- *
- * [0, 0, N] -> locked by N shared access threads, if N=0 it's unlocked
- * [0, >=1, >=1] -> threads are requesting exclusive locks, but there are
- * still shared access threads inside. #shared should not be incremented
- * anymore!
- * [1, >=1, >=0] -> lock is owned by an exclusive thread and the #shared
- * counter can be used again to count the number of threads waiting in the
- * queue for shared access.
- *
- * the following states are invalid and will never occur:
- * [0, >=1, 0], [1, 0, >=0]
- *
- * The main problem arising from the fact that we have no separate counter
- * of shared access threads inside the locked section is that in the state
- * [0, >=1, >=1] above we cannot add additional waiting threads to the
- * shared access queue - it wouldn't be possible to distinguish waiting
- * threads and those that are still inside. To solve this problem the lock
- * uses the following approach: a thread that isn't able to allocate a
- * shared lock just uses the exclusive queue instead. As soon as the thread
- * is woken up it is in the state [1, >=1, >=0]. In this state it's again
- * possible to use the shared access queue. The thread atomically moves
- * itself to the shared access queue and releases the exclusive lock, so
- * that the "real" exclusive access threads have a chance. As soon as they
- * are all ready the shared access threads are processed.
- */
-
-#define SRWLOCK_MASK_IN_EXCLUSIVE 0x80000000
-#define SRWLOCK_MASK_EXCLUSIVE_QUEUE 0x7fff0000
-#define SRWLOCK_MASK_SHARED_QUEUE 0x0000ffff
-#define SRWLOCK_RES_EXCLUSIVE 0x00010000
-#define SRWLOCK_RES_SHARED 0x00000001
-
-#ifdef WORDS_BIGENDIAN
-#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1))
-#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1))
-#else
-#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1))
-#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1))
-#endif
-
-static inline void srwlock_check_invalid( unsigned int val )
+struct srw_lock
{
- /* Throw exception if it's impossible to acquire/release this lock. */
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) == SRWLOCK_MASK_EXCLUSIVE_QUEUE ||
- (val & SRWLOCK_MASK_SHARED_QUEUE) == SRWLOCK_MASK_SHARED_QUEUE)
- RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);
-}
+ short exclusive_waiters;
-static inline unsigned int srwlock_lock_exclusive( unsigned int *dest, int incr )
-{
- unsigned int val, tmp;
- /* Atomically modifies the value of *dest by adding incr. If the shared
- * queue is empty and there are threads waiting for exclusive access, then
- * sets the mark SRWLOCK_MASK_IN_EXCLUSIVE to signal other threads that
- * they are allowed again to use the shared queue counter. */
- for (val = *dest;; val = tmp)
- {
- tmp = val + incr;
- srwlock_check_invalid( tmp );
- if ((tmp & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(tmp & SRWLOCK_MASK_SHARED_QUEUE))
- tmp |= SRWLOCK_MASK_IN_EXCLUSIVE;
- if ((tmp = InterlockedCompareExchange( (int *)dest, tmp, val )) == val)
- break;
- }
- return val;
-}
-
-static inline unsigned int srwlock_unlock_exclusive( unsigned int *dest, int incr )
-{
- unsigned int val, tmp;
- /* Atomically modifies the value of *dest by adding incr. If the queue of
- * threads waiting for exclusive access is empty, then remove the
- * SRWLOCK_MASK_IN_EXCLUSIVE flag (only the shared queue counter will
- * remain). */
- for (val = *dest;; val = tmp)
- {
- tmp = val + incr;
- srwlock_check_invalid( tmp );
- if (!(tmp & SRWLOCK_MASK_EXCLUSIVE_QUEUE))
- tmp &= SRWLOCK_MASK_SHARED_QUEUE;
- if ((tmp = InterlockedCompareExchange( (int *)dest, tmp, val )) == val)
- break;
- }
- return val;
-}
-
-static inline void srwlock_leave_exclusive( RTL_SRWLOCK *lock, unsigned int val )
-{
- /* Used when a thread leaves an exclusive section. If there are other
- * exclusive access threads they are processed first, followed by
- * the shared waiters. */
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
- NtReleaseKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
- else
- {
- val &= SRWLOCK_MASK_SHARED_QUEUE; /* remove SRWLOCK_MASK_IN_EXCLUSIVE */
- while (val--)
- NtReleaseKeyedEvent( 0, srwlock_key_shared(lock), FALSE, NULL );
- }
-}
-
-static inline void srwlock_leave_shared( RTL_SRWLOCK *lock, unsigned int val )
-{
- /* Wake up one exclusive thread as soon as the last shared access thread
- * has left. */
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_SHARED_QUEUE))
- NtReleaseKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
-}
+ /* Number of shared owners, or -1 if owned exclusive.
+ *
+ * Sadly Windows has no equivalent to FUTEX_WAIT_BITSET, so in order to wake
+ * up *only* exclusive or *only* shared waiters (and thus avoid spurious
+ * wakeups), we need to wait on two different addresses.
+ * RtlAcquireSRWLockShared() needs to know the values of "exclusive_waiters"
+ * and "owners", but RtlAcquireSRWLockExclusive() only needs to know the
+ * value of "owners", so the former can wait on the entire structure, and
+ * the latter waits only on the "owners" member. Note then that "owners"
+ * must not be the first element in the structure.
+ */
+ short owners;
+};
+C_ASSERT( sizeof(struct srw_lock) == 4 );
/***********************************************************************
* RtlInitializeSRWLock (NTDLL.@)
@@ -650,11 +547,36 @@ void WINAPI RtlInitializeSRWLock( RTL_SRWLOCK *lock )
*/
void WINAPI RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
{
- if (unix_funcs->fast_RtlAcquireSRWLockExclusive( lock ) != STATUS_NOT_IMPLEMENTED)
- return;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
- if (srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, SRWLOCK_RES_EXCLUSIVE ))
- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
+ InterlockedIncrement16( &u.s->exclusive_waiters );
+
+ for (;;)
+ {
+ union { struct srw_lock s; LONG l; } old, new;
+ BOOL wait;
+
+ do
+ {
+ old.s = *u.s;
+ new.s = old.s;
+
+ if (!old.s.owners)
+ {
+ /* Not locked exclusive or shared. We can try to grab it. */
+ new.s.owners = -1;
+ --new.s.exclusive_waiters;
+ wait = FALSE;
+ }
+ else
+ {
+ wait = TRUE;
+ }
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ if (!wait) return;
+ RtlWaitOnAddress( &u.s->owners, &new.s.owners, sizeof(short), NULL );
+ }
}
/***********************************************************************
@@ -666,34 +588,34 @@ void WINAPI RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
*/
void WINAPI RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
{
- unsigned int val, tmp;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
- if (unix_funcs->fast_RtlAcquireSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED)
- return;
-
- /* Acquires a shared lock. If it's currently not possible to add elements to
- * the shared queue, then request exclusive access instead. */
- for (val = *(unsigned int *)&lock->Ptr;; val = tmp)
+ for (;;)
{
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_IN_EXCLUSIVE))
- tmp = val + SRWLOCK_RES_EXCLUSIVE;
- else
- tmp = val + SRWLOCK_RES_SHARED;
- if ((tmp = InterlockedCompareExchange( (int *)&lock->Ptr, tmp, val )) == val)
- break;
- }
+ union { struct srw_lock s; LONG l; } old, new;
+ BOOL wait;
- /* Drop exclusive access again and instead requeue for shared access. */
- if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) && !(val & SRWLOCK_MASK_IN_EXCLUSIVE))
- {
- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL );
- val = srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr, (SRWLOCK_RES_SHARED
- - SRWLOCK_RES_EXCLUSIVE) ) - SRWLOCK_RES_EXCLUSIVE;
- srwlock_leave_exclusive( lock, val );
- }
+ do
+ {
+ old.s = *u.s;
+ new = old;
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
- NtWaitForKeyedEvent( 0, srwlock_key_shared(lock), FALSE, NULL );
+ if (old.s.owners != -1 && !old.s.exclusive_waiters)
+ {
+ /* Not locked exclusive, and no exclusive waiters.
+ * We can try to grab it. */
+ ++new.s.owners;
+ wait = FALSE;
+ }
+ else
+ {
+ wait = TRUE;
+ }
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ if (!wait) return;
+ RtlWaitOnAddress( u.s, &new.s, sizeof(struct srw_lock), NULL );
+ }
}
/***********************************************************************
@@ -701,11 +623,23 @@ void WINAPI RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
*/
void WINAPI RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
{
- if (unix_funcs->fast_RtlReleaseSRWLockExclusive( lock ) != STATUS_NOT_IMPLEMENTED)
- return;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
+ union { struct srw_lock s; LONG l; } old, new;
- srwlock_leave_exclusive( lock, srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr,
- - SRWLOCK_RES_EXCLUSIVE ) - SRWLOCK_RES_EXCLUSIVE );
+ do
+ {
+ old.s = *u.s;
+ new = old;
+
+ if (old.s.owners != -1) ERR("Lock %p is not owned exclusive!\n", lock);
+
+ new.s.owners = 0;
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ if (new.s.exclusive_waiters)
+ RtlWakeAddressSingle( &u.s->owners );
+ else
+ RtlWakeAddressAll( u.s );
}
/***********************************************************************
@@ -713,11 +647,22 @@ void WINAPI RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
*/
void WINAPI RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
{
- if (unix_funcs->fast_RtlReleaseSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED)
- return;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
+ union { struct srw_lock s; LONG l; } old, new;
- srwlock_leave_shared( lock, srwlock_lock_exclusive( (unsigned int *)&lock->Ptr,
- - SRWLOCK_RES_SHARED ) - SRWLOCK_RES_SHARED );
+ do
+ {
+ old.s = *u.s;
+ new = old;
+
+ if (old.s.owners == -1) ERR("Lock %p is owned exclusive!\n", lock);
+ else if (!old.s.owners) ERR("Lock %p is not owned shared!\n", lock);
+
+ --new.s.owners;
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ if (!new.s.owners)
+ RtlWakeAddressSingle( &u.s->owners );
}
/***********************************************************************
@@ -729,13 +674,28 @@ void WINAPI RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
*/
BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
{
- NTSTATUS ret;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
+ union { struct srw_lock s; LONG l; } old, new;
+ BOOLEAN ret;
- if ((ret = unix_funcs->fast_RtlTryAcquireSRWLockExclusive( lock )) != STATUS_NOT_IMPLEMENTED)
- return (ret == STATUS_SUCCESS);
+ do
+ {
+ old.s = *u.s;
+ new.s = old.s;
- return InterlockedCompareExchange( (int *)&lock->Ptr, SRWLOCK_MASK_IN_EXCLUSIVE |
- SRWLOCK_RES_EXCLUSIVE, 0 ) == 0;
+ if (!old.s.owners)
+ {
+ /* Not locked exclusive or shared. We can try to grab it. */
+ new.s.owners = -1;
+ ret = TRUE;
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ return ret;
}
/***********************************************************************
@@ -743,20 +703,29 @@ BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
*/
BOOLEAN WINAPI RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
{
- unsigned int val, tmp;
- NTSTATUS ret;
+ union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock };
+ union { struct srw_lock s; LONG l; } old, new;
+ BOOLEAN ret;
- if ((ret = unix_funcs->fast_RtlTryAcquireSRWLockShared( lock )) != STATUS_NOT_IMPLEMENTED)
- return (ret == STATUS_SUCCESS);
-
- for (val = *(unsigned int *)&lock->Ptr;; val = tmp)
+ do
{
- if (val & SRWLOCK_MASK_EXCLUSIVE_QUEUE)
- return FALSE;
- if ((tmp = InterlockedCompareExchange( (int *)&lock->Ptr, val + SRWLOCK_RES_SHARED, val )) == val)
- break;
- }
- return TRUE;
+ old.s = *u.s;
+ new.s = old.s;
+
+ if (old.s.owners != -1 && !old.s.exclusive_waiters)
+ {
+ /* Not locked exclusive, and no exclusive waiters.
+ * We can try to grab it. */
+ ++new.s.owners;
+ ret = TRUE;
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l);
+
+ return ret;
}
/***********************************************************************
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 32aa7267423..3d26da194e4 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -2145,12 +2145,6 @@ static struct unix_funcs unix_funcs =
NtCurrentTeb,
#endif
RtlGetSystemTimePrecise,
- fast_RtlTryAcquireSRWLockExclusive,
- fast_RtlAcquireSRWLockExclusive,
- fast_RtlTryAcquireSRWLockShared,
- fast_RtlAcquireSRWLockShared,
- fast_RtlReleaseSRWLockExclusive,
- fast_RtlReleaseSRWLockShared,
load_so_dll,
init_builtin_dll,
init_unix_lib,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 7a2466f5fa3..0065f265e42 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -110,8 +110,6 @@ static inline ULONGLONG monotonic_counter(void)
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
-#define FUTEX_WAIT_BITSET 9
-#define FUTEX_WAKE_BITSET 10
static int futex_private = 128;
@@ -125,16 +123,6 @@ static inline int futex_wake( const int *addr, int val )
return syscall( __NR_futex, addr, FUTEX_WAKE | futex_private, val, NULL, 0, 0 );
}
-static inline int futex_wait_bitset( const int *addr, int val, struct timespec *timeout, int mask )
-{
- return syscall( __NR_futex, addr, FUTEX_WAIT_BITSET | futex_private, val, timeout, 0, mask );
-}
-
-static inline int futex_wake_bitset( const int *addr, int val, int mask )
-{
- return syscall( __NR_futex, addr, FUTEX_WAKE_BITSET | futex_private, val, NULL, 0, mask );
-}
-
static inline int use_futexes(void)
{
static int supported = -1;
@@ -152,16 +140,6 @@ static inline int use_futexes(void)
return supported;
}
-static int *get_futex(void **ptr)
-{
- if (sizeof(void *) == 8)
- return (int *)((((ULONG_PTR)ptr) + 3) & ~3);
- else if (!(((ULONG_PTR)ptr) & 3))
- return (int *)ptr;
- else
- return NULL;
-}
-
#endif
@@ -2532,289 +2510,3 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
}
#endif
-
-#ifdef __linux__
-
-/* Futex-based SRW lock implementation:
- *
- * Since we can rely on the kernel to release all threads and don't need to
- * worry about NtReleaseKeyedEvent(), we can simplify the layout a bit. The
- * layout looks like this:
- *
- * 31 - Exclusive lock bit, set if the resource is owned exclusively.
- * 30-16 - Number of exclusive waiters. Unlike the fallback implementation,
- * this does not include the thread owning the lock, or shared threads
- * waiting on the lock.
- * 15 - Does this lock have any shared waiters? We use this as an
- * optimization to avoid unnecessary FUTEX_WAKE_BITSET calls when
- * releasing an exclusive lock.
- * 14-0 - Number of shared owners. Unlike the fallback implementation, this
- * does not include the number of shared threads waiting on the lock.
- * Thus the state [1, x, >=1] will never occur.
- */
-
-#define SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT 0x80000000
-#define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK 0x7fff0000
-#define SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC 0x00010000
-#define SRWLOCK_FUTEX_SHARED_WAITERS_BIT 0x00008000
-#define SRWLOCK_FUTEX_SHARED_OWNERS_MASK 0x00007fff
-#define SRWLOCK_FUTEX_SHARED_OWNERS_INC 0x00000001
-
-/* Futex bitmasks; these are independent from the bits in the lock itself. */
-#define SRWLOCK_FUTEX_BITSET_EXCLUSIVE 1
-#define SRWLOCK_FUTEX_BITSET_SHARED 2
-
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- int old, new, *futex;
- NTSTATUS ret;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- do
- {
- old = *futex;
-
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
- && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
- {
- /* Not locked exclusive or shared. We can try to grab it. */
- new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
- ret = STATUS_SUCCESS;
- }
- else
- {
- new = old;
- ret = STATUS_TIMEOUT;
- }
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- return ret;
-}
-
-NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- int old, new, *futex;
- BOOLEAN wait;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- /* Atomically increment the exclusive waiter count. */
- do
- {
- old = *futex;
- new = old + SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
- assert(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- for (;;)
- {
- do
- {
- old = *futex;
-
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
- && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
- {
- /* Not locked exclusive or shared. We can try to grab it. */
- new = old | SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
- assert(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK);
- new -= SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC;
- wait = FALSE;
- }
- else
- {
- new = old;
- wait = TRUE;
- }
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- if (!wait)
- return STATUS_SUCCESS;
-
- futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
-{
- int new, old, *futex;
- NTSTATUS ret;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- do
- {
- old = *futex;
-
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
- && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
- {
- /* Not locked exclusive, and no exclusive waiters. We can try to
- * grab it. */
- new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
- assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
- ret = STATUS_SUCCESS;
- }
- else
- {
- new = old;
- ret = STATUS_TIMEOUT;
- }
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- return ret;
-}
-
-NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
-{
- int old, new, *futex;
- BOOLEAN wait;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- for (;;)
- {
- do
- {
- old = *futex;
-
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
- && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
- {
- /* Not locked exclusive, and no exclusive waiters. We can try
- * to grab it. */
- new = old + SRWLOCK_FUTEX_SHARED_OWNERS_INC;
- assert(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK);
- wait = FALSE;
- }
- else
- {
- new = old | SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
- wait = TRUE;
- }
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- if (!wait)
- return STATUS_SUCCESS;
-
- futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_SHARED );
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- int old, new, *futex;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- do
- {
- old = *futex;
-
- if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT))
- {
- ERR("Lock %p is not owned exclusive! (%#x)\n", lock, *futex);
- return STATUS_RESOURCE_NOT_OWNED;
- }
-
- new = old & ~SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT;
-
- if (!(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
- new &= ~SRWLOCK_FUTEX_SHARED_WAITERS_BIT;
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- if (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)
- futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
- else if (old & SRWLOCK_FUTEX_SHARED_WAITERS_BIT)
- futex_wake_bitset( futex, INT_MAX, SRWLOCK_FUTEX_BITSET_SHARED );
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
-{
- int old, new, *futex;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- if (!(futex = get_futex( &lock->Ptr )))
- return STATUS_NOT_IMPLEMENTED;
-
- do
- {
- old = *futex;
-
- if (old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)
- {
- ERR("Lock %p is owned exclusive! (%#x)\n", lock, *futex);
- return STATUS_RESOURCE_NOT_OWNED;
- }
- else if (!(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK))
- {
- ERR("Lock %p is not owned shared! (%#x)\n", lock, *futex);
- return STATUS_RESOURCE_NOT_OWNED;
- }
-
- new = old - SRWLOCK_FUTEX_SHARED_OWNERS_INC;
- } while (InterlockedCompareExchange( futex, new, old ) != old);
-
- /* Optimization: only bother waking if there are actually exclusive waiters. */
- if (!(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK) && (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK))
- futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
-
- return STATUS_SUCCESS;
-}
-
-#else
-
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-#endif
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 61f37d4b22f..b499978b2fe 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -100,12 +100,6 @@ extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PT
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
extern void (WINAPI *p__wine_ctrl_routine)(void *) DECLSPEC_HIDDEN;
extern SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern LONGLONG CDECL fast_RtlGetSystemTimePrecise(void) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispatch,
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index a271bb05da9..803b6a082bb 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -26,7 +26,7 @@
struct _DISPATCHER_CONTEXT;
/* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 131
+#define NTDLL_UNIXLIB_VERSION 132
struct unix_funcs
{
@@ -38,14 +38,6 @@ struct unix_funcs
/* other Win32 API functions */
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
- /* fast locks */
- NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockShared)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock );
- NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock );
-
/* loader functions */
NTSTATUS (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module );
void (CDECL *init_builtin_dll)( void *module );
--
2.33.0

View File

@ -1 +0,0 @@
Fixes: [50292] Process-local synchronization objects use private interfaces into the Unix library

View File

@ -51,7 +51,7 @@ usage()
# Get the upstream commit sha
upstream_commit()
{
echo "161d61481f5d5ab8ee0b6237853af830e992afb1"
echo "32fb017d4a22be38ca271bf387e466e958601355"
}
# Show version information
@ -149,7 +149,6 @@ patch_enable_all ()
enable_ntdll_Hide_Wine_Exports="$1"
enable_ntdll_Junction_Points="$1"
enable_ntdll_Manifest_Range="$1"
enable_ntdll_NtAlertThreadByThreadId="$1"
enable_ntdll_NtQueryEaFile="$1"
enable_ntdll_NtQuerySection="$1"
enable_ntdll_NtSetLdtEntries="$1"
@ -478,9 +477,6 @@ patch_enable ()
ntdll-Manifest_Range)
enable_ntdll_Manifest_Range="$2"
;;
ntdll-NtAlertThreadByThreadId)
enable_ntdll_NtAlertThreadByThreadId="$2"
;;
ntdll-NtQueryEaFile)
enable_ntdll_NtQueryEaFile="$2"
;;
@ -2496,23 +2492,6 @@ if test "$enable_ntdll_Manifest_Range" -eq 1; then
patch_apply ntdll-Manifest_Range/0001-ntdll-Support-ISOLATIONAWARE_MANIFEST_RESOURCE_ID-ra.patch
fi
# Patchset ntdll-NtAlertThreadByThreadId
# |
# | This patchset fixes the following Wine bugs:
# | * [#50292] Process-local synchronization objects use private interfaces into the Unix library
# |
# | Modified files:
# | * dlls/ntdll/sync.c, dlls/ntdll/unix/loader.c, dlls/ntdll/unix/sync.c, dlls/ntdll/unix/unix_private.h,
# | dlls/ntdll/unixlib.h
# |
if test "$enable_ntdll_NtAlertThreadByThreadId" -eq 1; then
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/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
fi
# Patchset ntdll-NtQuerySection
# |
# | Modified files:

View File

@ -1,4 +1,4 @@
From b3cbf1c996a0a6f9533aa4461f77df08c123f74d Mon Sep 17 00:00:00 2001
From 9a550439fe370711ce1a2146753aa41026d5fb2a Mon Sep 17 00:00:00 2001
From: Ken Thomases <ken@codeweavers.com>
Date: Tue, 22 Jun 2021 07:56:43 +1000
Subject: [PATCH] winemac.drv: No Flicker patch
@ -10,7 +10,7 @@ Subject: [PATCH] winemac.drv: No Flicker patch
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index a7c0b4cac87..be119c50d48 100644
index d73a52fa35f..f85973de13d 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -41,6 +41,7 @@
@ -22,7 +22,7 @@ index a7c0b4cac87..be119c50d48 100644
extern const char* debugstr_cf(CFTypeRef t) DECLSPEC_HIDDEN;
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 203e993ee93..2e5c1329a2a 100644
index d8d16b1f4df..09fee166a05 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -63,6 +63,7 @@ int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
@ -44,10 +44,10 @@ index 203e993ee93..2e5c1329a2a 100644
processes in the prefix. */
if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer)))
diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c
index 9f02e93d376..f3d4e2850e7 100644
index 33132de7415..b2c66296d9c 100644
--- a/dlls/winemac.drv/opengl.c
+++ b/dlls/winemac.drv/opengl.c
@@ -1477,7 +1477,7 @@ static BOOL create_context(struct wgl_context *context, CGLContextObj share, uns
@@ -1465,7 +1465,7 @@ static BOOL create_context(struct wgl_context *context, CGLContextObj share, uns
attribs[n++] = pf->samples;
}
@ -55,7 +55,7 @@ index 9f02e93d376..f3d4e2850e7 100644
+ if (force_backing_store || pf->backing_store)
attribs[n++] = kCGLPFABackingStore;
#if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (core)
--
2.30.2
2.33.0

View File

@ -1 +1 @@
161d61481f5d5ab8ee0b6237853af830e992afb1
32fb017d4a22be38ca271bf387e466e958601355