mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Rebase against 32fb017d4a22be38ca271bf387e466e958601355.
This commit is contained in:
parent
7e42d0ac1a
commit
d3d93cfa0d
@ -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
|
||||
|
@ -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( ×pec, timeout );
|
||||
- ret = futex_wait( futex, val, ×pec );
|
||||
- }
|
||||
- else
|
||||
- ret = futex_wait( futex, val, NULL );
|
||||
-
|
||||
- if (ret == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-static inline NTSTATUS fast_wake_addr( const void *addr )
|
||||
-{
|
||||
- int *futex;
|
||||
-
|
||||
- if (!use_futexes())
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- futex = hash_addr( addr );
|
||||
-
|
||||
- InterlockedIncrement( futex );
|
||||
-
|
||||
- futex_wake( futex, INT_MAX );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
#else
|
||||
|
||||
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
@@ -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
|
||||
|
@ -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, ×pec ) == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- }
|
||||
- return STATUS_WAIT_0;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- *(int *)&crit->LockSemaphore = 1;
|
||||
- futex_wake( (int *)&crit->LockSemaphore, 1 );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-#elif defined(__APPLE__)
|
||||
-
|
||||
-static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_t ret = *(int *)&crit->LockSemaphore;
|
||||
- if (!ret)
|
||||
- {
|
||||
- semaphore_t sem;
|
||||
- if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) return 0;
|
||||
- if (!(ret = InterlockedCompareExchange( (int *)&crit->LockSemaphore, sem, 0 )))
|
||||
- ret = sem;
|
||||
- else
|
||||
- semaphore_destroy( mach_task_self(), sem ); /* somebody beat us to it */
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- mach_timespec_t timespec;
|
||||
- semaphore_t sem = get_mach_semaphore( crit );
|
||||
-
|
||||
- timespec.tv_sec = timeout;
|
||||
- timespec.tv_nsec = 0;
|
||||
- for (;;)
|
||||
- {
|
||||
- switch( semaphore_timedwait( sem, timespec ))
|
||||
- {
|
||||
- case KERN_SUCCESS:
|
||||
- return STATUS_WAIT_0;
|
||||
- case KERN_ABORTED:
|
||||
- continue; /* got a signal, restart */
|
||||
- case KERN_OPERATION_TIMED_OUT:
|
||||
- return STATUS_TIMEOUT;
|
||||
- default:
|
||||
- return STATUS_INVALID_HANDLE;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_t sem = get_mach_semaphore( crit );
|
||||
- semaphore_signal( sem );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- semaphore_destroy( mach_task_self(), *(int *)&crit->LockSemaphore );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-#else /* __APPLE__ */
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
-{
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
#ifdef __linux__
|
||||
|
||||
/* Futex-based SRW lock implementation:
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 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
|
||||
|
@ -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( ×pec, timeout );
|
||||
- ret = futex_wait( futex, aligned_value, ×pec );
|
||||
- }
|
||||
- else
|
||||
- ret = futex_wait( futex, aligned_value, NULL );
|
||||
-
|
||||
- if (ret == -1 && errno == ETIMEDOUT)
|
||||
- return STATUS_TIMEOUT;
|
||||
- return STATUS_WAIT_0;
|
||||
-}
|
||||
-
|
||||
-NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
|
||||
-{
|
||||
- int *futex;
|
||||
-
|
||||
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- if (!(futex = get_futex( &variable->Ptr )))
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-
|
||||
- InterlockedIncrement( futex );
|
||||
- futex_wake( futex, count );
|
||||
- return STATUS_SUCCESS;
|
||||
-}
|
||||
-
|
||||
#else
|
||||
|
||||
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||
@@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
Fixes: [50292] Process-local synchronization objects use private interfaces into the Unix library
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -1 +1 @@
|
||||
161d61481f5d5ab8ee0b6237853af830e992afb1
|
||||
32fb017d4a22be38ca271bf387e466e958601355
|
||||
|
Loading…
Reference in New Issue
Block a user