From 17e0fb2e0be8d53b485c96941faaa76d30d0c032 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 | 9 +++++++ 3 files changed, 57 insertions(+) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index f4f87ba5642..7d6423083e1 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2301,6 +2301,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()) { @@ -2312,6 +2316,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) #endif NtSetEvent( thread_data->tid_alert_event, NULL ); return STATUS_SUCCESS; +#endif } } @@ -2349,6 +2354,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()) { @@ -2384,6 +2427,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 87f5a97131e..e97a9657f03 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 2da19c6844f..3c4d5dd8a2b 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -27,6 +27,11 @@ #include "wine/server.h" #include "wine/list.h" +#ifdef __APPLE__ +# include +# include +#endif + #ifdef __i386__ static const enum cpu_type client_cpu = CPU_x86; static const WORD current_machine = IMAGE_FILE_MACHINE_I386; @@ -62,10 +67,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.20.1