Skip to content

Instantly share code, notes, and snippets.

@heiher
Created September 13, 2022 02:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heiher/a57c787e2f2d4f313df8cdf13086824e to your computer and use it in GitHub Desktop.
Save heiher/a57c787e2f2d4f313df8cdf13086824e to your computer and use it in GitHub Desktop.
Atomic mark benchmark
/*
============================================================================
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