ntdll: Implement thread-ID alerts using Mach semaphores on Mac.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
161d61481f
commit
842ecb45f4
|
@ -2341,10 +2341,14 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
|
||||||
|
|
||||||
union tid_alert_entry
|
union tid_alert_entry
|
||||||
{
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
semaphore_t sem;
|
||||||
|
#else
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int futex;
|
int futex;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry))
|
#define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry))
|
||||||
|
@ -2379,6 +2383,17 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid )
|
||||||
|
|
||||||
entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE];
|
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__
|
#ifdef __linux__
|
||||||
if (use_futexes())
|
if (use_futexes())
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -2393,6 +2408,7 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid )
|
||||||
if (InterlockedCompareExchangePointer( &entry->event, event, NULL ))
|
if (InterlockedCompareExchangePointer( &entry->event, event, NULL ))
|
||||||
NtClose( event );
|
NtClose( event );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
@ -2409,6 +2425,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||||
|
|
||||||
if (!entry) return STATUS_INVALID_CID;
|
if (!entry) return STATUS_INVALID_CID;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
semaphore_signal( entry->sem );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
#else
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (use_futexes())
|
if (use_futexes())
|
||||||
{
|
{
|
||||||
|
@ -2420,10 +2440,11 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NtSetEvent( entry->event, NULL );
|
return NtSetEvent( entry->event, NULL );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
static LONGLONG get_absolute_timeout( const LARGE_INTEGER *timeout )
|
static LONGLONG get_absolute_timeout( const LARGE_INTEGER *timeout )
|
||||||
{
|
{
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
|
@ -2446,6 +2467,57 @@ static LONGLONG update_timeout( ULONGLONG end )
|
||||||
#endif
|
#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.@)
|
* NtWaitForAlertByThreadId (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
|
@ -2498,6 +2570,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue