You couldn't export builtin functions, but you can do hack with gcc
gcc -shared -fPIC -O2 atomic_ops.c -o libatomic_ops.so
#include <stdint.h>
#include <stdbool.h>
// Ensure all functions are exported from the shared library
#define EXPORT __attribute__((visibility("default")))
// 32-bit compare and swap
EXPORT
bool __sync_bool_compare_and_swap_4(volatile void* ptr, uint32_t oldval, uint32_t newval) {
bool result;
__asm__ __volatile__(
"lock; cmpxchgl %2, %1\n\t"
"sete %0"
: "=q" (result), "+m" (*(volatile uint32_t*)ptr)
: "r" (newval), "a" (oldval)
: "memory", "cc"
);
return result;
}
// 64-bit compare and swap
EXPORT
bool __sync_bool_compare_and_swap_8(volatile void* ptr, uint64_t oldval, uint64_t newval) {
bool result;
__asm__ __volatile__(
"lock; cmpxchgq %2, %1\n\t"
"sete %0"
: "=q" (result), "+m" (*(volatile uint64_t*)ptr)
: "r" (newval), "a" (oldval)
: "memory", "cc"
);
return result;
}
// 32-bit fetch and add
EXPORT
uint32_t __sync_fetch_and_add_4(volatile void* ptr, uint32_t value) {
__asm__ __volatile__(
"lock; xaddl %0, %1"
: "+r" (value), "+m" (*(volatile uint32_t*)ptr)
:
: "memory"
);
return value;
}
// 32-bit fetch and or
EXPORT
uint32_t __sync_fetch_and_or_4(volatile void* ptr, uint32_t value) {
uint32_t result, temp;
__asm__ __volatile__(
"1:\n\t"
"movl %1, %0\n\t"
"movl %0, %2\n\t"
"orl %3, %2\n\t"
"lock; cmpxchgl %2, %1\n\t"
"jne 1b"
: "=&a" (result), "+m" (*(volatile uint32_t*)ptr), "=&r" (temp)
: "r" (value)
: "memory", "cc"
);
return result;
}
// 32-bit val compare and swap
EXPORT
uint32_t __sync_val_compare_and_swap_4(volatile void* ptr, uint32_t oldval, uint32_t newval) {
uint32_t result;
__asm__ __volatile__(
"lock; cmpxchgl %2, %1"
: "=a" (result), "+m" (*(volatile uint32_t*)ptr)
: "r" (newval), "0" (oldval)
: "memory"
);
return result;
}
// 64-bit val compare and swap
EXPORT
uint64_t __sync_val_compare_and_swap_8(volatile void* ptr, uint64_t oldval, uint64_t newval) {
uint64_t result;
__asm__ __volatile__(
"lock; cmpxchgq %2, %1"
: "=a" (result), "+m" (*(volatile uint64_t*)ptr)
: "r" (newval), "0" (oldval)
: "memory"
);
return result;
}
// Additional commonly used atomic operations
// 32-bit atomic increment
EXPORT
uint32_t __sync_add_and_fetch_4(volatile void* ptr, uint32_t value) {
uint32_t result;
__asm__ __volatile__(
"lock; xaddl %0, %1"
: "=r" (result), "+m" (*(volatile uint32_t*)ptr)
: "0" (value)
: "memory"
);
return result + value;
}
// 32-bit atomic decrement
EXPORT
uint32_t __sync_sub_and_fetch_4(volatile void* ptr, uint32_t value) {
return __sync_add_and_fetch_4(ptr, -value);
}
// 32-bit atomic AND
EXPORT
uint32_t __sync_fetch_and_and_4(volatile void* ptr, uint32_t value) {
uint32_t result, temp;
__asm__ __volatile__(
"1:\n\t"
"movl %1, %0\n\t"
"movl %0, %2\n\t"
"andl %3, %2\n\t"
"lock; cmpxchgl %2, %1\n\t"
"jne 1b"
: "=&a" (result), "+m" (*(volatile uint32_t*)ptr), "=&r" (temp)
: "r" (value)
: "memory", "cc"
);
return result;
}
// 32-bit atomic XOR
EXPORT
uint32_t __sync_fetch_and_xor_4(volatile void* ptr, uint32_t value) {
uint32_t result, temp;
__asm__ __volatile__(
"1:\n\t"
"movl %1, %0\n\t"
"movl %0, %2\n\t"
"xorl %3, %2\n\t"
"lock; cmpxchgl %2, %1\n\t"
"jne 1b"
: "=&a" (result), "+m" (*(volatile uint32_t*)ptr), "=&r" (temp)
: "r" (value)
: "memory", "cc"
);
return result;
}