https://bugs.winehq.org/show_bug.cgi?id=46208
--- Comment #13 from Brendan McGrath brendan@redmandi.com --- (In reply to Zebediah Figura from comment #11)
One alternative is to have an implementation almost identical to the futex path, but which uses RtlWaitOnAddress()/RtlWakeAddress() instead. It'd be horrendously slow, but I think we should be able to use native sync objects on all the platforms we care about.
This works. As a proof of concept I applied the futex patch and modified the futex_wait and futex_wake to be:
static inline int futex_wait( int *addr, int val, struct timespec *timeout ) { LARGE_INTEGER li_timeout; LARGE_INTEGER *p_li_timeout;
if (timeout) { li_timeout.LowPart = timeout->tv_sec * TICKSPERSEC + timeout->tv_nsec; p_li_timeout = &li_timeout; } else { p_li_timeout = NULL; }
return RtlWaitOnAddress( addr, &val, sizeof(val), p_li_timeout ); }
static inline int futex_wake( int *addr, int val ) { if (val == INT_MAX) RtlWakeAddressAll(addr); else RtlWakeAddressSingle(addr);
return STATUS_SUCCESS; }
Obviously my 'struct timeout' to LARGE_INTEGER conversion is prone to overflow and my formatting is terrible - but this was just proof of concept.
It worked without needing the two recent patches you submitted for RtlWaitOnAddress too.