-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspin.c
110 lines (89 loc) · 1.99 KB
/
spin.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bench.h"
#define assert(x) if(__builtin_expect((x), 0)) __builtin_trap()
#define assert_eq(x,y) \
do { \
if((x) != (y)) { \
printf("ERROR %s %ld != %ld\n", #x, (long)(x), (long)(y)); \
__builtin_trap(); \
} \
} while (0)
struct mbox {
unsigned lock;
unsigned count;
unsigned a[2];
}__attribute__((aligned(64))) mbox;
static bool mbox_lock(struct mbox *mbx)
{
#if 0
unsigned lock = 0;
while(!__atomic_compare_exchange_n(
&mbx->lock, &lock, 1, false,
__ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
while ((lock = __atomic_load_n(&mbx->lock, __ATOMIC_ACQUIRE)) != 0)
;
#else
while (__atomic_test_and_set(&mbx->lock, __ATOMIC_ACQUIRE))
while ((__atomic_load_n(&mbx->lock, __ATOMIC_ACQUIRE)) != 0)
;
#endif
return true;
}
static void mbox_unlock(struct mbox *mbx)
{
assert_eq(mbx->lock, 1);
#if 0
// __atomic_store_n(&mbx->lock, 0, __ATOMIC_RELEASE);
#else
__atomic_clear(&mbx->lock,__ATOMIC_RELEASE);
#endif
}
void mbox_inc(struct mbox *mbx, size_t id)
{
mbox_lock(mbx);
assert_eq(mbx->lock,1);
mbx->count++;
mbx->a[id]++;
mbox_unlock(mbx);
}
void inc(size_t n, size_t id)
{
for (size_t i = 0; i < n; i++) {
mbox_inc(&mbox, id);
}
printf("a = %u, b = %u\n", mbox.a[0], mbox.a[1]);
}
void benchmark_ping(struct thrarg *arg)
{
inc(arg->params.iters,arg->params.id);
}
void init(struct thrarg *arg)
{
(void)arg;
memset(&mbox, 0, sizeof(struct mbox));
}
int main(int argc, char **argv)
{
unsigned nthreads = 2;
(void)argc; (void)argv;
struct thrarg thrarg = { .params = {
.threads = nthreads,
.benchmark = benchmark_ping,
.init = init,
.min_time = 100*1000,
// .max_samples = 10,
// .iters = 10,
}};
int err = benchmark_auto(&thrarg);
// int err = benchmark_once(&thrarg);
if (err < 0) {
fprintf(stderr, "Bench error %s\n", strerror(err));
return 1;
}
printf("%.2f %.2f %.2f\n", thrarg.result.avg, thrarg.result.err, thrarg.result.u);
return 0;
}