Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
//#define NCOUNT (1000000)
#define NCOUNT (100000)
#define TCOUNT (20)
volatile uint64_t u = 0;
volatile uint64_t *casvar = &u;
pthread_mutex_t lock;
volatile uint64_t global = 0;
int mutex = 0;
uint64_t
cas(volatile uint64_t *v, uint64_t old, uint64_t new)
{
uint64_t ret = 0;
if ((uint64_t)v & 0xff != 0)
return 42;
asm volatile (
" add %0, zero, 1\n\t"
" lr.d.aqrl a0, (%1)\n\t"
" bne %2, a0, done\n\t"
" sc.d.aqrl %0, %3, (%1)\n\t"
"done:\n"
: "+r" (ret)
: "r" (v), "r" (old), "r" (new)
: "a0"
);
return ret;
}
void *
thread(void *args) {
int i;
int tid = (uint64_t)args;
printf("in thread %d\n", tid);
for (i = 0; i < NCOUNT; i++) {
if (mutex) {
pthread_mutex_lock(&lock);
} else {
for (;;) {
uint64_t x = cas(casvar, 0, tid);
if (x != 0) {
//printf("tid %d cas %d\n", tid, x);
//usleep(1000000);
continue;
}
break;
}
}
//printf("locked tid %d\n", tid);
global += 1;
if (mutex) {
pthread_mutex_unlock(&lock);
} else {
u = 0; // unlock, yes not atomic!
}
}
return (NULL);
}
int
main(int argc, char **argv)
{
uint64_t i;
pthread_t tid[TCOUNT];
mutex = 0;
if (pthread_mutex_init(&lock, NULL) != 0) {
printf(" mutex init\n");
return (1);
}
for (int i = 0; i < TCOUNT; i++) {
pthread_create(&tid[i], NULL, thread, (void *)i+10);
}
for (i = 0; i < TCOUNT; i++) {
int jr = pthread_join(tid[i], NULL);
if (jr) {
printf("pthread_join failed %d %d\n", i+10, jr);
// exit?
}
}
if (global != TCOUNT*NCOUNT) {
printf("womp womp %d %d\n", global, TCOUNT*NCOUNT);
return (1);
}
printf("ok %d %d\n", global, TCOUNT*NCOUNT);
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment