In this link achieve GCC cas function for version 4.1.2 and earlier I ask a question to use compare_and_swap
function to achieve the Built-in function __sync_fetch_and_add
here is my final code, run well in x86 and x64 (tested on CentOS 5.0 32bit and CentOS 7 64bit ).
Here is my code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static unsigned long count = 0;
int sync_add_and_fetch(int* reg, int oldval, int incre)
{
register char result;
#ifdef __i386__
__asm__ volatile ("lock; cmpxchgl %3, %0; setz %1"
: "=m"(*reg), "=q" (result)
: "m" (*reg), "r" (oldval + incre), "a" (oldval)
: "memory");
return result;
#elif defined(__x86_64__)
__asm__ volatile ("lock; cmpxchgq %3, %0; setz %1"
: "=m"(*reg), "=q" (result)
: "m" (*reg), "r" (newval + incre), "a" (oldval)
: "memory");
return result;
#else
#error:architecture not supported and gcc too old
#endif
}
void *test_func(void *arg)
{
int i = 0;
int result = 0;
for(i = 0; i < 2000; ++i)
{
result = 0;
while(0 == result)
{
result = sync_add_and_fetch((int *)&count, count, 1);
}
}
return NULL;
}
int main(int argc, const char *argv[])
{
pthread_t id[10];
int i = 0;
for(i = 0; i < 10; ++i){
pthread_create(&id[i], NULL, test_func, NULL);
}
for(i = 0; i < 10; ++i){
pthread_join(id[i], NULL);
}
//10*2000=200000
printf("%u\n", count);
return 0;
}
Now I have another question, how to implement function InterlockedExchange
in Linux, InterlockedExchange just like the code above, have a __i386__
and __x86_64__
version. Just use the code above the parameter type not match, and maybe the assembly code will be rewritten.