From 171a3f3e3a73bc58c4b16826df3fb4f459fd05e2 Mon Sep 17 00:00:00 2001 From: Ganesh Kumar Durairaj Date: Tue, 2 Sep 2025 01:29:17 -0700 Subject: [PATCH] [#162] Fix 64bit atomic api issues for 32bit system-part2 *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 add and subtract operator. --- include/click/atomic.hh | 83 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/include/click/atomic.hh b/include/click/atomic.hh index 53f8bc0b2..c38e052e5 100644 --- a/include/click/atomic.hh +++ b/include/click/atomic.hh @@ -858,10 +858,34 @@ atomic_uint64_t::operator+=(int64_t delta) #elif CLICK_ATOMIC_BUILTINS __atomic_add_fetch(&_val, delta, CLICK_ATOMIC_MEMORDER); #elif CLICK_ATOMIC_X86 - asm volatile (CLICK_ATOMIC_LOCK "addq %1,%0" + #if defined(__x86_64__) + asm volatile (CLICK_ATOMIC_LOCK "addq %1,%0" : "=m" (CLICK_ATOMIC_VAL) : "r" (delta), "m" (CLICK_ATOMIC_VAL) : "cc"); + #else + uint32_t dlow = static_cast(delta & 0xFFFFFFFF); + int32_t dhigh = static_cast(delta >> 32); + + asm volatile ( + "movl %%ebx, %%esi\n\t" // Save EBX (needed for PIC) + "1:\n\t" + "movl (%[addr]), %%eax\n\t" // EAX = old low + "movl 4(%[addr]), %%edx\n\t" // EDX = old high + "movl %%eax, %%ebx\n\t" // EBX = expected low + "movl %%edx, %%ecx\n\t" // ECX = expected high + "addl %[delta_low], %%ebx\n\t" // EBX = new low + "adcl %[delta_high], %%ecx\n\t" // ECX = new high (+ carry) + CLICK_ATOMIC_LOCK "cmpxchg8b (%[addr])\n\t" // Atomically compare and exchange + "jnz 1b\n\t" // Retry if comparison failed + "movl %%esi, %%ebx\n\t" // Restore EBX + : + : [addr] "r" (&_val), + [delta_low] "m" (dlow), + [delta_high] "m" (dhigh) // sign-extend high part + : "eax", "edx", "ecx", "esi", "memory" + ); + #endif #else CLICK_ATOMIC_VAL += delta; #endif @@ -877,10 +901,32 @@ atomic_uint64_t::add(volatile uint64_t &x, uint64_t delta) #elif CLICK_ATOMIC_BUILTINS __atomic_add_fetch(&x, delta, CLICK_ATOMIC_MEMORDER); #elif CLICK_ATOMIC_X86 - asm volatile (CLICK_ATOMIC_LOCK "addq %1,%0" - : "=m" (x) - : "r" (delta), "m" (x) - : "cc"); + #if defined(__x86_64__) + asm volatile (CLICK_ATOMIC_LOCK "addq %1,%0" + : "=m" (x) + : "r" (delta), "m" (x) + : "cc"); + #else + uint32_t dlow = static_cast(delta & 0xFFFFFFFF); + uint32_t dhigh = static_cast(delta >> 32); + asm volatile ( + "movl %%ebx, %%esi\n\t" // Save EBX + "1:\n\t" + "movl (%[addr]), %%eax\n\t" // EAX = old low + "movl 4(%[addr]), %%edx\n\t" // EDX = old high + "movl %%eax, %%ebx\n\t" // EBX = expected low + "movl %%edx, %%ecx\n\t" // ECX = expected high + "addl %[delta_low], %%ebx\n\t" // EBX = new low + "adcl %[delta_high], %%ecx\n\t" // ECX = new high (+ carry) + CLICK_ATOMIC_LOCK "cmpxchg8b (%[addr])\n\t" // Try to atomically swap + "jnz 1b\n\t" // Retry if failed + "movl %%esi, %%ebx\n\t" // Restore EBX + : + : [addr] "r" (&x), + [delta_low] "m" (dlow), + [delta_high] "m" (dhigh) + : "eax", "edx", "ecx", "esi", "memory"); + #endif #else x += delta; #endif @@ -895,10 +941,29 @@ atomic_uint64_t::operator-=(int64_t delta) #elif CLICK_ATOMIC_BUILTINS __atomic_sub_fetch(&CLICK_ATOMIC_VAL, delta, CLICK_ATOMIC_MEMORDER); #elif CLICK_ATOMIC_X86 - asm volatile (CLICK_ATOMIC_LOCK "subq %1,%0" - : "=m" (CLICK_ATOMIC_VAL) - : "r" (delta), "m" (CLICK_ATOMIC_VAL) - : "cc"); + #if defined(__x86_64__) + asm volatile (CLICK_ATOMIC_LOCK "subq %1,%0" + : "=m" (CLICK_ATOMIC_VAL) + : "r" (delta), "m" (CLICK_ATOMIC_VAL) + : "cc"); + #else + uint32_t dlow = static_cast(delta & 0xFFFFFFFF); + int32_t dhigh = static_cast(delta >> 32); + asm volatile("1:\n\t" + "movl (%[addr]), %%eax\n\t" // EAX = old low + "movl 4(%[addr]), %%edx\n\t" // EDX = old high + "movl %%eax, %%ebx\n\t" // EBX = old low + "movl %%edx, %%ecx\n\t" // ECX = old high + "subl %[vlo], %%ebx\n\t" // EBX -= value low + "sbbl %[vhi], %%ecx\n\t" // ECX -= value high + borrow + CLICK_ATOMIC_LOCK "cmpxchg8b (%[addr])\n\t" // Attempt atomic CAS + "jnz 1b\n\t" // Retry if it failed + : + : [addr] "r" (&_val), + [vlo] "m" (dlow), + [vhi] "m" (dhigh) + : "eax", "ebx", "ecx", "edx", "memory"); + #endif #else CLICK_ATOMIC_VAL -= delta; #endif