Atomic flip bit benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
============================================================================ | |
Name : atomic-flip-bit-bench.c | |
Author : Rui Wang <wangrui@loongson.cn> | |
Copyright : Copyright (c) 2022 hev | |
Description : Atomic flip bit benchmark | |
============================================================================ | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <pthread.h> | |
#define THREADS 8 | |
#define LOOPS 10000000 | |
typedef void (*FlipFunc) (int); | |
static long svar; | |
static FlipFunc flip; | |
static inline long | |
cmpxchg (volatile long *addr, long oldval, long newval) | |
{ | |
return __sync_val_compare_and_swap (addr, oldval, newval); | |
} | |
static inline long | |
fetch_and_xor (volatile long *addr, long val) | |
{ | |
return __sync_fetch_and_xor (addr, val); | |
} | |
static void | |
flip_cas (int shift) | |
{ | |
volatile long *pv = &svar; | |
const long val = 1UL << shift; | |
long i; | |
for (i = 0; i < LOOPS; i++) { | |
long oldval = *pv; | |
do { | |
const long newval = oldval ^ val; | |
const long curval = cmpxchg (pv, oldval, newval); | |
if (oldval == curval) | |
break; | |
oldval = curval; | |
} while (1); | |
} | |
} | |
static void | |
flip_amo (int shift) | |
{ | |
volatile long *pv = &svar; | |
const long val = 1UL << shift; | |
long i; | |
for (i = 0; i < LOOPS; i++) { | |
fetch_and_xor (pv, val); | |
} | |
} | |
static void * | |
thread_handler (void *data) | |
{ | |
const int mask = sizeof (long) * 8 - 1; | |
flip ((intptr_t)data & mask); | |
return NULL; | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
pthread_t threads[THREADS]; | |
int i; | |
if (argc < 2) { | |
fprintf (stderr, "%s cas | amo\n", argv[0]); | |
return -1; | |
} | |
if (strcmp (argv[1], "cas") == 0) { | |
flip = flip_cas; | |
} else { | |
flip = flip_amo; | |
} | |
for (i = 0; i < THREADS; i++) { | |
int res; | |
res = pthread_create (&threads[i], NULL, thread_handler, | |
(void *)(intptr_t)i); | |
assert (res == 0); | |
} | |
for (i = 0; i < THREADS; i++) { | |
assert (pthread_join (threads[i], NULL) == 0); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment