2010年10月28日星期四

CAS/CAS2 for lock free queue on x86_64

Just ported lock-free queue to x86_64

here is CAS, CAS2 macros


#ifdef __x86_64__
#define __xg(x) ((volatile long *)(x)) // stole from linux kernel source

// CAS2(ret, &q->tail, head, tag2, next, tag2 + 1);

#define CAS2(ret, mem, old1, old2, new1, new2) \
do {\
asm volatile( \
".align 8 \n" \
"movq $0, %0 \n" \
"LOCK cmpxchg16b %1\n" \
"setz %0 \n" \
"1:\n" \
: "=m" (ret) \
: "m" (*__xg(mem)), "a" (old1), "d" (old2), "b" (new1), "c" (new2) \
: "memory", "cc" \
); \
/* ret = ( (ret & (1 <<>
} while(0);

#else
#define CAS2(ret, mem, old1, old2, new1, new2) \
do {\
asm volatile( \
".align 4 \n" \
"movl $0, %0 \n" \
"LOCK cmpxchg8b (%%esi)\n" \
"setz %0 \n" \
"1:\n" \
: "=m" (ret) \
: "S" (mem), "a" (old1), "d" (old2), "b" (new1), "c" (new2) \
: "memory", "cc" \
); \
/* ret = ( (ret & (1 <<>
} while(0);
#endif

#define DEAD_NODE(q) \
&((q)->stone)


#ifdef __x86_64__

#define CAS(ret, mem, old, new) \
do {\
asm volatile( \
".align 8 \n" \
"movq $0, %0 \n" \
"LOCK cmpxchgq %1, %2 \n" \
"setz %0 \n" \
: "=m" (ret) \
: "d" (new), "m" (*__xg(mem)), "a" (old) \
: "memory", "cc" \
); \
} while(0);

#else
#define CAS(ret, mem, old, new) \
do {\
asm volatile( \
".align 4 \n" \
"movl $0, %0 \n" \
"LOCK cmpxchgl %%edx, (%%esi) \n" \
"setz %0 \n" \
: "=m" (ret) \
: "d" (new), "S" (mem), "a" (old) \
: "memory", "cc" \
); \
} while(0);
#endif

Note: you will have to use long/unsigned long type for each variables for CAS/CAS2, if use int type, gcc might use e*x registers as operand of q suffix instructions, it will make you very unhappy.

没有评论: