Created
September 13, 2022 02:45
-
-
Save heiher/a57c787e2f2d4f313df8cdf13086824e to your computer and use it in GitHub Desktop.
Atomic mark 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-mark-bench.c | |
Author : Rui Wang <wangrui@loongson.cn> | |
Copyright : Copyright (c) 2022 hev | |
Description : Atomic mark benchmark | |
============================================================================ | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <pthread.h> | |
#define THREADS 16 | |
#define LOOPS 100000000 | |
typedef void (*BitOpFunc) (int); | |
static long svar; | |
static BitOpFunc mark; | |
static inline long | |
fetch_and_or (volatile long *addr, long val) | |
{ | |
return __sync_fetch_and_or (addr, val); | |
} | |
static inline long | |
fetch_and_xor (volatile long *addr, long val) | |
{ | |
return __sync_fetch_and_xor (addr, val); | |
} | |
static void | |
mark_amo (int shift) | |
{ | |
volatile long *pv = &svar; | |
const long val = 1UL << shift; | |
long i; | |
for (i = 0; i < LOOPS; i++) { | |
fetch_and_or (pv, val); | |
} | |
} | |
static void | |
mark_amo_fast (int shift) | |
{ | |
volatile long *pv = &svar; | |
const long val = 1UL << shift; | |
long i; | |
long curval = *pv; | |
for (i = 0; i < LOOPS; i++) { | |
// fast path | |
const long newval = curval | val; | |
if (curval == newval) | |
continue; | |
// slow path | |
curval = fetch_and_or (pv, val); | |
} | |
} | |
static void * | |
mark_handler (void *data) | |
{ | |
const int mask = sizeof (long) * 8 - 1; | |
mark ((intptr_t)data & mask); | |
return NULL; | |
} | |
static void * | |
flip_handler (void *data) | |
{ | |
volatile long *pv = &svar; | |
const int bits = sizeof (long) * 8; | |
int i; | |
for (i = 0; i < bits; i++) { | |
fetch_and_xor (pv, 1UL << i); | |
} | |
return NULL; | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
pthread_t threads[THREADS]; | |
pthread_t flip_thread; | |
int i, res; | |
if (argc < 2) { | |
fprintf (stderr, "%s norm | fast\n", argv[0]); | |
return -1; | |
} | |
if (strcmp (argv[1], "fast") == 0) { | |
mark = mark_amo_fast; | |
} else { | |
mark = mark_amo; | |
} | |
res = pthread_create (&flip_thread, NULL, flip_handler, NULL); | |
assert (res == 0); | |
for (i = 0; i < THREADS; i++) { | |
res = pthread_create (&threads[i], NULL, mark_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