From 4c58c278a16e77650b1a3626df6e43cb603089e2 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:03:34 -0500 Subject: [PATCH] ntdll: Implement thread-id alerts on top of Mach semaphores on Mac. Signed-off-by: Zebediah Figura --- dlls/ntdll/unix/sync.c | 44 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/thread.c | 4 ++++ dlls/ntdll/unix/unix_private.h | 8 +++++++ 3 files changed, 56 insertions(+) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 05a478ae464..377a34c0824 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2144,6 +2144,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) if (teb->ClientId.UniqueThread == tid) { pthread_rwlock_unlock( &teb_list_lock ); +#ifdef __APPLE__ + semaphore_signal( thread_data->tid_alert_sem ); + return STATUS_SUCCESS; +#else #ifdef __linux__ if (use_futexes()) { @@ -2155,6 +2159,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) #endif NtSetEvent( thread_data->tid_alert_event, NULL ); return STATUS_SUCCESS; +#endif } } @@ -2192,6 +2197,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG { TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); +#ifdef __APPLE__ + { + semaphore_t sem = ntdll_get_thread_data()->tid_alert_sem; + ULONGLONG end; + kern_return_t ret; + + 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 #ifdef __linux__ if (use_futexes()) { @@ -2227,6 +2270,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG } #endif return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); +#endif } diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index bb55b3d29ed..05157e24ace 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -252,7 +252,11 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT thread_data->start = start; thread_data->param = param; +#ifdef __APPLE__ + semaphore_create( mach_task_self(), &thread_data->tid_alert_sem, SYNC_POLICY_FIFO, 0 ); +#else NtCreateEvent( &thread_data->tid_alert_event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); +#endif pthread_attr_init( &pthread_attr ); pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 7e733052c87..dc1c379c790 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -26,6 +26,10 @@ #include "unixlib.h" #include "wine/list.h" +#ifdef __APPLE__ +# include +#endif + #ifdef __i386__ static const enum cpu_type client_cpu = CPU_x86; #elif defined(__x86_64__) @@ -57,10 +61,14 @@ struct ntdll_thread_data struct list entry; /* entry in TEB list */ PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ +#ifdef __APPLE__ + semaphore_t tid_alert_sem; /* Mach semaphore for thread-id alerts */ +#else #ifdef __linux__ int tid_alert_futex; /* futex for thread-id alerts */ #endif HANDLE tid_alert_event; /* event for thread-id alerts */ +#endif }; C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -- 2.29.2