Module: wine Branch: master Commit: e200e0194e6b1b9d5abae0c5f33ce72aa20849ce URL: https://gitlab.winehq.org/wine/wine/-/commit/e200e0194e6b1b9d5abae0c5f33ce72...
Author: Marc-Aurel Zent mzent@codeweavers.com Date: Tue Mar 5 13:05:21 2024 +0100
ntdll: Prefer futex for thread-ID alerts over kqueue.
---
dlls/ntdll/unix/sync.c | 122 ++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 68 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 1d66f0d974f..1cad7dc8662 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2409,10 +2409,10 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
union tid_alert_entry { -#ifdef HAVE_KQUEUE - int kq; -#elif defined(__linux__) +#ifdef __linux__ LONG futex; +#elif defined(HAVE_KQUEUE) + int kq; #else HANDLE event; #endif @@ -2450,7 +2450,9 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid )
entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE];
-#ifdef HAVE_KQUEUE +#ifdef __linux__ + return entry; +#elif defined(HAVE_KQUEUE) if (!entry->kq) { int kq = kqueue(); @@ -2480,8 +2482,6 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) if (InterlockedCompareExchange( (LONG *)&entry->kq, kq, 0 )) close( kq ); } -#elif defined(__linux__) - return entry; #else if (!entry->event) { @@ -2509,7 +2509,14 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
if (!entry) return STATUS_INVALID_CID;
-#ifdef HAVE_KQUEUE +#ifdef __linux__ + { + LONG *futex = &entry->futex; + if (!InterlockedExchange( futex, 1 )) + futex_wake( futex, 1 ); + return STATUS_SUCCESS; + } +#elif defined(HAVE_KQUEUE) { static const struct kevent signal_event = { @@ -2524,13 +2531,6 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) kevent( entry->kq, &signal_event, 1, NULL, 0, NULL ); return STATUS_SUCCESS; } -#elif defined(__linux__) - { - LONG *futex = &entry->futex; - if (!InterlockedExchange( futex, 1 )) - futex_wake( futex, 1 ); - return STATUS_SUCCESS; - } #else return NtSetEvent( entry->event, NULL ); #endif @@ -2560,59 +2560,6 @@ static LONGLONG update_timeout( ULONGLONG end ) #endif
-#ifdef HAVE_KQUEUE - -/*********************************************************************** - * NtWaitForAlertByThreadId (NTDLL.@) - */ -NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout ) -{ - union tid_alert_entry *entry = get_tid_alert_entry( NtCurrentTeb()->ClientId.UniqueThread ); - ULONGLONG end; - int ret; - struct timespec timespec; - struct kevent wait_event; - - TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); - - if (!entry) return STATUS_INVALID_CID; - - if (timeout) - { - if (timeout->QuadPart == TIMEOUT_INFINITE) - timeout = NULL; - else - end = get_absolute_timeout( timeout ); - } - - do - { - if (timeout) - { - LONGLONG timeleft = update_timeout( end ); - - timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; - timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100; - if (timespec.tv_sec > 0x7FFFFFFF) timeout = NULL; - } - - ret = kevent( entry->kq, NULL, 0, &wait_event, 1, timeout ? ×pec : NULL ); - } while (ret == -1 && errno == EINTR); - - switch (ret) - { - case 1: - return STATUS_ALERTED; - case 0: - return STATUS_TIMEOUT; - default: - ERR( "kevent failed with error: %d (%s)\n", errno, strerror( errno ) ); - return STATUS_INVALID_HANDLE; - } -} - -#else - /*********************************************************************** * NtWaitForAlertByThreadId (NTDLL.@) */ @@ -2656,6 +2603,46 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG } return STATUS_ALERTED; } +#elif defined(HAVE_KQUEUE) + { + ULONGLONG end; + int ret; + struct timespec timespec; + struct kevent wait_event; + + if (timeout) + { + if (timeout->QuadPart == TIMEOUT_INFINITE) + timeout = NULL; + else + end = get_absolute_timeout( timeout ); + } + + do + { + if (timeout) + { + LONGLONG timeleft = update_timeout( end ); + + timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; + timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100; + if (timespec.tv_sec > 0x7FFFFFFF) timeout = NULL; + } + + ret = kevent( entry->kq, NULL, 0, &wait_event, 1, timeout ? ×pec : NULL ); + } while (ret == -1 && errno == EINTR); + + switch (ret) + { + case 1: + return STATUS_ALERTED; + case 0: + return STATUS_TIMEOUT; + default: + ERR( "kevent failed with error: %d (%s)\n", errno, strerror( errno ) ); + return STATUS_INVALID_HANDLE; + } + } #else { NTSTATUS status = NtWaitForSingleObject( entry->event, FALSE, timeout ); @@ -2665,7 +2652,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG #endif }
-#endif
/*********************************************************************** * NtCreateTransaction (NTDLL.@)