ntdll: Move the wait on address implementation to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
509ad75adb
commit
552bc8aa47
|
@ -4382,8 +4382,6 @@ void __wine_process_init(void)
|
||||||
init_user_process_params( info_size );
|
init_user_process_params( info_size );
|
||||||
params = peb->ProcessParameters;
|
params = peb->ProcessParameters;
|
||||||
|
|
||||||
NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
|
|
||||||
|
|
||||||
/* retrieve current umask */
|
/* retrieve current umask */
|
||||||
FILE_umask = umask(0777);
|
FILE_umask = umask(0777);
|
||||||
umask( FILE_umask );
|
umask( FILE_umask );
|
||||||
|
|
|
@ -213,7 +213,6 @@ static inline int get_unix_exit_code( NTSTATUS status )
|
||||||
}
|
}
|
||||||
|
|
||||||
extern mode_t FILE_umask DECLSPEC_HIDDEN;
|
extern mode_t FILE_umask DECLSPEC_HIDDEN;
|
||||||
extern HANDLE keyed_event DECLSPEC_HIDDEN;
|
|
||||||
extern SYSTEM_CPU_INFORMATION cpu_info DECLSPEC_HIDDEN;
|
extern SYSTEM_CPU_INFORMATION cpu_info DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#define HASH_STRING_ALGORITHM_DEFAULT 0
|
#define HASH_STRING_ALGORITHM_DEFAULT 0
|
||||||
|
|
|
@ -63,66 +63,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||||
|
|
||||||
HANDLE keyed_event = NULL;
|
|
||||||
|
|
||||||
static const LARGE_INTEGER zero_timeout;
|
|
||||||
|
|
||||||
#define TICKSPERSEC 10000000
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
#define FUTEX_WAIT 0
|
|
||||||
#define FUTEX_WAKE 1
|
|
||||||
#define FUTEX_WAIT_BITSET 9
|
|
||||||
#define FUTEX_WAKE_BITSET 10
|
|
||||||
|
|
||||||
static int futex_private = 128;
|
|
||||||
|
|
||||||
static inline int futex_wait( const int *addr, int val, struct timespec *timeout )
|
|
||||||
{
|
|
||||||
return syscall( __NR_futex, addr, FUTEX_WAIT | futex_private, val, timeout, 0, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 use_futexes(void)
|
|
||||||
{
|
|
||||||
static int supported = -1;
|
|
||||||
|
|
||||||
if (supported == -1)
|
|
||||||
{
|
|
||||||
futex_wait( &supported, 10, NULL );
|
|
||||||
if (errno == ENOSYS)
|
|
||||||
{
|
|
||||||
futex_private = 0;
|
|
||||||
futex_wait( &supported, 10, NULL );
|
|
||||||
}
|
|
||||||
supported = (errno != ENOSYS);
|
|
||||||
}
|
|
||||||
return supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
/* creates a struct security_descriptor and contained information in one contiguous piece of memory */
|
/* creates 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,
|
NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||||
data_size_t *ret_len )
|
data_size_t *ret_len )
|
||||||
|
@ -1558,145 +1498,13 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RTL_CRITICAL_SECTION addr_section;
|
|
||||||
static RTL_CRITICAL_SECTION_DEBUG addr_section_debug =
|
|
||||||
{
|
|
||||||
0, 0, &addr_section,
|
|
||||||
{ &addr_section_debug.ProcessLocksList, &addr_section_debug.ProcessLocksList },
|
|
||||||
0, 0, { (DWORD_PTR)(__FILE__ ": addr_section") }
|
|
||||||
};
|
|
||||||
static RTL_CRITICAL_SECTION addr_section = { &addr_section_debug, -1, 0, 0, 0, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
/* 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
|
|
||||||
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.@)
|
* RtlWaitOnAddress (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
|
NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
|
||||||
const LARGE_INTEGER *timeout )
|
const LARGE_INTEGER *timeout )
|
||||||
{
|
{
|
||||||
select_op_t select_op;
|
return unix_funcs->RtlWaitOnAddress( addr, cmp, size, timeout );
|
||||||
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;
|
|
||||||
|
|
||||||
RtlEnterCriticalSection( &addr_section );
|
|
||||||
if (!compare_addr( addr, cmp, size ))
|
|
||||||
{
|
|
||||||
RtlLeaveCriticalSection( &addr_section );
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abs_timeout < 0)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER now;
|
|
||||||
|
|
||||||
RtlQueryPerformanceCounter(&now);
|
|
||||||
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 unix_funcs->server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE, abs_timeout, NULL, &addr_section, NULL );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1704,12 +1512,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||||
*/
|
*/
|
||||||
void WINAPI RtlWakeAddressAll( const void *addr )
|
void WINAPI RtlWakeAddressAll( const void *addr )
|
||||||
{
|
{
|
||||||
if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED)
|
return unix_funcs->RtlWakeAddressAll( addr );
|
||||||
return;
|
|
||||||
|
|
||||||
RtlEnterCriticalSection( &addr_section );
|
|
||||||
while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
|
|
||||||
RtlLeaveCriticalSection( &addr_section );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1717,10 +1520,5 @@ void WINAPI RtlWakeAddressAll( const void *addr )
|
||||||
*/
|
*/
|
||||||
void WINAPI RtlWakeAddressSingle( const void *addr )
|
void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||||
{
|
{
|
||||||
if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED)
|
return unix_funcs->RtlWakeAddressSingle( addr );
|
||||||
return;
|
|
||||||
|
|
||||||
RtlEnterCriticalSection( &addr_section );
|
|
||||||
NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
|
|
||||||
RtlLeaveCriticalSection( &addr_section );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1046,6 +1046,9 @@ static struct unix_funcs unix_funcs =
|
||||||
NtWriteVirtualMemory,
|
NtWriteVirtualMemory,
|
||||||
NtYieldExecution,
|
NtYieldExecution,
|
||||||
DbgUiIssueRemoteBreakin,
|
DbgUiIssueRemoteBreakin,
|
||||||
|
RtlWaitOnAddress,
|
||||||
|
RtlWakeAddressAll,
|
||||||
|
RtlWakeAddressSingle,
|
||||||
fast_RtlTryAcquireSRWLockExclusive,
|
fast_RtlTryAcquireSRWLockExclusive,
|
||||||
fast_RtlAcquireSRWLockExclusive,
|
fast_RtlAcquireSRWLockExclusive,
|
||||||
fast_RtlTryAcquireSRWLockShared,
|
fast_RtlTryAcquireSRWLockShared,
|
||||||
|
@ -1082,7 +1085,6 @@ static struct unix_funcs unix_funcs =
|
||||||
exit_process,
|
exit_process,
|
||||||
get_thread_ldt_entry,
|
get_thread_ldt_entry,
|
||||||
wine_server_call,
|
wine_server_call,
|
||||||
server_select,
|
|
||||||
server_wait,
|
server_wait,
|
||||||
server_send_fd,
|
server_send_fd,
|
||||||
server_get_unix_fd,
|
server_get_unix_fd,
|
||||||
|
|
|
@ -602,9 +602,9 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* server_select
|
* server_select
|
||||||
*/
|
*/
|
||||||
unsigned int CDECL server_select( const select_op_t *select_op, data_size_t size, UINT flags,
|
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
|
||||||
timeout_t abs_timeout, CONTEXT *context, RTL_CRITICAL_SECTION *cs,
|
timeout_t abs_timeout, CONTEXT *context, RTL_CRITICAL_SECTION *cs,
|
||||||
user_apc_t *user_apc )
|
user_apc_t *user_apc )
|
||||||
{
|
{
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
int cookie;
|
int cookie;
|
||||||
|
|
|
@ -71,6 +71,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||||
|
|
||||||
HANDLE keyed_event = 0;
|
HANDLE keyed_event = 0;
|
||||||
|
|
||||||
|
static const LARGE_INTEGER zero_timeout;
|
||||||
|
|
||||||
|
static RTL_CRITICAL_SECTION addr_section;
|
||||||
|
static RTL_CRITICAL_SECTION_DEBUG addr_section_debug =
|
||||||
|
{
|
||||||
|
0, 0, &addr_section,
|
||||||
|
{ &addr_section_debug.ProcessLocksList, &addr_section_debug.ProcessLocksList },
|
||||||
|
0, 0, { (DWORD_PTR)(__FILE__ ": addr_section") }
|
||||||
|
};
|
||||||
|
static RTL_CRITICAL_SECTION addr_section = { &addr_section_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
#define FUTEX_WAIT 0
|
#define FUTEX_WAIT 0
|
||||||
|
@ -147,6 +158,24 @@ static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGE
|
||||||
#endif
|
#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 */
|
/* 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,
|
NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||||
data_size_t *ret_len )
|
data_size_t *ret_len )
|
||||||
|
@ -1358,6 +1387,71 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable,
|
||||||
return STATUS_SUCCESS;
|
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
|
#else
|
||||||
|
|
||||||
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
|
||||||
|
@ -1407,4 +1501,78 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable,
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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
|
#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;
|
||||||
|
|
||||||
|
RtlEnterCriticalSection( &addr_section );
|
||||||
|
if (!compare_addr( addr, cmp, size ))
|
||||||
|
{
|
||||||
|
RtlLeaveCriticalSection( &addr_section );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abs_timeout < 0)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER now;
|
||||||
|
|
||||||
|
RtlQueryPerformanceCounter(&now);
|
||||||
|
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_section, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* RtlWakeAddressAll (NTDLL.@)
|
||||||
|
*/
|
||||||
|
void WINAPI RtlWakeAddressAll( const void *addr )
|
||||||
|
{
|
||||||
|
if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
|
||||||
|
|
||||||
|
RtlEnterCriticalSection( &addr_section );
|
||||||
|
while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
|
||||||
|
RtlLeaveCriticalSection( &addr_section );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* RtlWakeAddressSingle (NTDLL.@)
|
||||||
|
*/
|
||||||
|
void WINAPI RtlWakeAddressSingle( const void *addr )
|
||||||
|
{
|
||||||
|
if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED) return;
|
||||||
|
|
||||||
|
RtlEnterCriticalSection( &addr_section );
|
||||||
|
NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
|
||||||
|
RtlLeaveCriticalSection( &addr_section );
|
||||||
|
}
|
||||||
|
|
|
@ -91,9 +91,6 @@ extern void CDECL virtual_set_force_exec( BOOL enable ) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;
|
extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
|
extern void CDECL virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern unsigned int CDECL server_select( const select_op_t *select_op, data_size_t size, UINT flags,
|
|
||||||
timeout_t abs_timeout, CONTEXT *context, RTL_CRITICAL_SECTION *cs,
|
|
||||||
user_apc_t *user_apc ) DECLSPEC_HIDDEN;
|
|
||||||
extern unsigned int CDECL server_wait( const select_op_t *select_op, data_size_t size, UINT flags,
|
extern unsigned int CDECL server_wait( const select_op_t *select_op, data_size_t size, UINT flags,
|
||||||
const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||||
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
|
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
|
||||||
|
@ -128,6 +125,11 @@ extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
|
||||||
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
||||||
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
||||||
extern void start_server( BOOL debug ) DECLSPEC_HIDDEN;
|
extern void start_server( BOOL debug ) DECLSPEC_HIDDEN;
|
||||||
|
extern unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
|
||||||
|
timeout_t abs_timeout, CONTEXT *context, RTL_CRITICAL_SECTION *cs,
|
||||||
|
user_apc_t *user_apc ) DECLSPEC_HIDDEN;
|
||||||
|
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call,
|
||||||
|
apc_result_t *result ) DECLSPEC_HIDDEN;
|
||||||
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
||||||
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
|
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
|
||||||
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||||
|
@ -139,8 +141,6 @@ extern void wait_suspend( CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) DECLSPEC_HIDDEN;
|
extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
|
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
|
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call,
|
|
||||||
apc_result_t *result ) DECLSPEC_HIDDEN;
|
|
||||||
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||||
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,10 @@ struct unix_funcs
|
||||||
|
|
||||||
/* other Win32 API functions */
|
/* other Win32 API functions */
|
||||||
NTSTATUS (WINAPI *DbgUiIssueRemoteBreakin)( HANDLE process );
|
NTSTATUS (WINAPI *DbgUiIssueRemoteBreakin)( HANDLE process );
|
||||||
|
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 */
|
/* fast locks */
|
||||||
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
|
||||||
|
@ -199,9 +203,6 @@ struct unix_funcs
|
||||||
|
|
||||||
/* server functions */
|
/* server functions */
|
||||||
unsigned int (CDECL *server_call)( void *req_ptr );
|
unsigned int (CDECL *server_call)( void *req_ptr );
|
||||||
unsigned int (CDECL *server_select)( const select_op_t *select_op, data_size_t size, UINT flags,
|
|
||||||
timeout_t abs_timeout, CONTEXT *context, RTL_CRITICAL_SECTION *cs,
|
|
||||||
user_apc_t *user_apc );
|
|
||||||
unsigned int (CDECL *server_wait)( const select_op_t *select_op, data_size_t size, UINT flags,
|
unsigned int (CDECL *server_wait)( const select_op_t *select_op, data_size_t size, UINT flags,
|
||||||
const LARGE_INTEGER *timeout );
|
const LARGE_INTEGER *timeout );
|
||||||
void (CDECL *server_send_fd)( int fd );
|
void (CDECL *server_send_fd)( int fd );
|
||||||
|
|
Loading…
Reference in New Issue