Skip to content

Commit 17f82a9

Browse files
committed
[#162] Fix 64bit atomic api issues for 32bit system-part4
*atomic apis are using only 64 bit assembly instructions([add,sub,..]q which are not supported in 32bit systems and compilation errors observed due to that. Fixing the assembly instruction for the api's compare_swap and add fetch_and_add.
1 parent b81689f commit 17f82a9

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

include/click/atomic.hh

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,10 +1015,18 @@ atomic_uint64_t::compare_swap(volatile uint64_t &x, uint64_t expected, uint64_t
10151015
return __atomic_compare_exchange(&x,&expected,&desired,0,CLICK_ATOMIC_MEMORDER, CLICK_ATOMIC_MEMORDER)
10161016
? expected : x;
10171017
#elif CLICK_ATOMIC_X86
1018-
asm volatile (CLICK_ATOMIC_LOCK "cmpxchgq %2,%1"
1019-
: "=a" (expected), "=m" (x)
1020-
: "r" (desired), "0" (expected), "m" (x)
1021-
: "cc", "memory");
1018+
#if defined(__x86_64__)
1019+
asm volatile (CLICK_ATOMIC_LOCK "cmpxchgq %2,%1"
1020+
: "=a" (expected), "=m" (x)
1021+
: "r" (desired), "0" (expected), "m" (x)
1022+
: "cc", "memory");
1023+
#else
1024+
asm volatile (CLICK_ATOMIC_LOCK "cmpxchg8b %1\n\t" // Compare EDX:EAX with [mem], replace with ECX:EBX if equal
1025+
: "+A" (expected) //load expected into EAX:EDX
1026+
: "m" (x), // preload memory value to compare.
1027+
"b" ((uint32_t)desired), "c"((uint32_t) (desired>>32))
1028+
: "memory");
1029+
#endif
10221030
return expected;
10231031
#elif CLICK_LINUXMODULE && defined(cmpxchg)
10241032
return cmpxchg(&x, expected, desired);
@@ -1063,11 +1071,31 @@ atomic_uint64_t::fetch_and_add(uint64_t delta)
10631071
#if CLICK_ATOMIC_BUILTINS
10641072
return __atomic_fetch_add(&_val, delta, CLICK_ATOMIC_MEMORDER);
10651073
#elif CLICK_ATOMIC_X86
1066-
asm volatile (CLICK_ATOMIC_LOCK "xaddq %0,%1"
1067-
: "=r" (delta), "=m" (CLICK_ATOMIC_VAL)
1068-
: "0" (delta), "m" (CLICK_ATOMIC_VAL)
1069-
: "cc");
1070-
return delta;
1074+
#if defined(__x86_64__)
1075+
asm volatile (CLICK_ATOMIC_LOCK "xaddq %0,%1"
1076+
: "=r" (delta), "=m" (CLICK_ATOMIC_VAL)
1077+
: "0" (delta), "m" (CLICK_ATOMIC_VAL)
1078+
: "cc");
1079+
return delta;
1080+
#else
1081+
uint32_t old_lo, old_hi;
1082+
asm volatile (
1083+
"1:\n\t"
1084+
"movl (%2), %%eax\n\t" // Load old low 32 bits
1085+
"movl 4(%2), %%edx\n\t" // Load old high 32 bits
1086+
"movl %%eax, %%ebx\n\t" // Copy low to ebx (new low)
1087+
"movl %%edx, %%ecx\n\t" // Copy high to ecx (new high)
1088+
"addl %3, %%ebx\n\t" // new low += delta low
1089+
"adcl %4, %%ecx\n\t" // new high += delta high + carry
1090+
CLICK_ATOMIC_LOCK "cmpxchg8b (%2)\n\t" // atomic cmpxchg8b
1091+
"jnz 1b\n\t" // if fail, retry
1092+
"movl %%eax, %0\n\t" // store old low
1093+
"movl %%edx, %1\n\t" // store old high
1094+
: "+a" (old_lo), "+d" (old_hi)
1095+
: "r" (&_val), "r" ((uint32_t)delta), "r" ((uint32_t)(delta >> 3))
1096+
: "ebx", "memory");
1097+
return (static_cast<uint64_t>(old_hi) << 32) | old_lo;
1098+
#endif
10711099
#elif CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_ADD_RETURN
10721100
return atomic64_add_return(&_val, delta) - delta;
10731101
#elif CLICK_LINUXMODULE

0 commit comments

Comments
 (0)