Reputation: 429
I am writing OS independent lockless queue, queue works fine (with default windows\linux atomic CAS), but I want to make queue work without any change in linux and windows. So I gues I should write my own CAS in assembler, or there is other ways to achieveit ?
So far I have this code:
global _CAS
_CAS:
mov eax, [esp+4]
mov edx, [esp+8]
mov ecx, [esp+12]
;XCHG eax, edx <- this function works fine
CMPXCHG ecx, eax, ebx
ret
I know that I still have to add lock
before CMPXCHG
and it should work with structures, but for now I'm more interested in making it working.
I compile using nasm-2.10.05 with this command nasm.exe -f elf -o cas.o cas.asm
and I get this error testas\cas.asm:14: error: invalid combination of opcode and operands
Upvotes: 3
Views: 3203
Reputation: 213308
With C11 or newer, you should be using <stdatomic.h>
, which has broad support these days:
#include <stdatomic.h>
See atomic_compare_exchange. I won't try and summarize the exact semantics here.
Without C11, you can do it with intrinsics on both platforms, no need for assembly:
#ifdef _MSC_VER
# include <intrin.h>
# define CAS(ptr, oldval, newval) \
_InterlockedCompareExchange(ptr, newval, oldval)
#elif __GNUC__
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
# error "requires GCC 4.1 or greater"
# endif
# define CAS(ptr, oldval, newval) \
__sync_val_compare_and_swap(ptr, oldval, newval)
#else
# error "CAS not supported on this platform"
#endif
Both of these support the following interface:
/* If the current value of *ptr is oldval, then write newval
into *ptr. Returns the initial value of *ptr. */
long CAS(long *ptr, long oldval, long newval);
See MSDN documentation, GCC documentation. This should also work on Clang with no modification, since Clang advertises __GNUC__
compatibility with its predefined macros.
Upvotes: 14
Reputation: 74018
According to http://web.itu.edu.tr/kesgin/mul06/intel/instr/cmpxchg.html, cmpxchg
takes two, not three parameters.
Maybe, http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=arch/x86/include/asm/cmpxchg.h is of interest too.
Upvotes: 5