From patch 2/4:
+# if HAVE_SYNC_COMPARE_AND_SWAP +static inline LONG InterlockedCompareExchange(LONG volatile *x, LONG xchg, LONG cmp) +{ + return __sync_val_compare_and_swap(x, cmp, xchg); +} +# else +# error "InterlockedCompareExchange() not implemented for this platform" +# endif +# if HAVE_ATOMIC_EXCHANGE_N +static inline LONG InterlockedExchange(LONG volatile *x, LONG val) +{ + return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST); +} +# elif HAVE_SYNC_COMPARE_AND_SWAP +static inline LONG InterlockedExchange(LONG volatile *x, LONG val) +{ + LONG i; + do + { + i = *x; + } while (__sync_val_compare_and_swap(x, i, val) != i); + return i; +} +# else +# error "InterlockedExchange() not implemented for this platform" +# endif
I imagine this follows the precedent set by InterlockedIncrement() and similar functions, but I think I'd prefer the approach taken for vkd3d_mutex_lock() and related functions, and introduce something like "vkd3d_atomic_compare_exchange()" and "vkd3d_atomic_exchange()" for these. Part of that is a style preference, but it would also avoid propagating Win32 types like LONG to the calling code.
Somewhat relatedly, patch 3/4 introduces "PVOID", and I think we should just use "void *".
Those comments aside, I'm inclined to approve this. I didn't do a very careful review of the locking; that means that if this were to break something, you'll get to fix it yourself. :)