-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathMCSK42.c
More file actions
110 lines (89 loc) · 2.57 KB
/
MCSK42.c
File metadata and controls
110 lines (89 loc) · 2.57 KB
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
// Michael L. Scott Shared-Memory Synchronization book, Figure 4.10, Chapter 4, page 12
#include <stdbool.h>
typedef struct mcs_node {
#ifndef ATOMIC
struct mcs_node * volatile tail, * volatile next;
#else
_Atomic(struct mcs_node *) tail, next; // distributes atomic
#endif // ! ATOMIC
} MCS_node CALIGN;
#define waiting ((MCS_node *)1)
static inline void mcs_lock( MCS_node * lock ) {
for ( ;; ) {
MCS_node * prev = lock->tail;
if ( prev == NULL ) {
if ( Cas( (lock->tail), NULL, lock ) ) break; // Fence
} else {
MCS_node n = { waiting, NULL };
if ( Cas( (lock->tail), prev, &n ) ) { // Fence
prev->next = &n;
await( n.tail != waiting );
MCS_node * succ = n.next;
if ( succ == NULL ) {
lock->next = NULL;
if ( ! Cas( (lock->tail), &n, lock ) ) { // Fence
await( (succ = n.next) != NULL );
WO( Fence(); );
lock->next = succ;
} // if
break;
} else {
lock->next = succ;
break;
} // if
} // if
} // if
} // for
WO( Fence(); );
} // mcs_lock
static inline void mcs_unlock( MCS_node * lock ) {
WO( Fence(); );
MCS_node * succ = lock->next;
if ( succ == NULL ) {
if ( Cas( (lock->tail), lock, NULL ) ) return; // Fence
await( (succ = lock->next) != NULL );
WO( Fence(); );
} // if
succ->tail = NULL;
} // mcs_unlock
static TYPE PAD1 CALIGN __attribute__(( unused )); // protect further false sharing
static MCS_node Lock CALIGN = { NULL, NULL };
static TYPE PAD2 CALIGN __attribute__(( unused )); // protect further false sharing
static void * Worker( void * arg ) {
TYPE id = (size_t)arg;
uint64_t entry;
#ifdef FAST
unsigned int cnt = 0, oid = id;
#endif // FAST
NCS_DECL;
for ( int r = 0; r < RUNS; r += 1 ) {
RTYPE randomThreadChecksum = 0;
for ( entry = 0; stop == 0; entry += 1 ) {
NCS;
mcs_lock( &Lock );
randomThreadChecksum += CS( id );
mcs_unlock( &Lock );
#ifdef FAST
id = startpoint( cnt ); // different starting point each experiment
cnt = cycleUp( cnt, NoStartPoints );
#endif // FAST
} // for
Fai( sumOfThreadChecksums, randomThreadChecksum );
#ifdef FAST
id = oid;
#endif // FAST
entries[r][id] = entry;
Fai( Arrived, 1 );
while ( stop != 0 ) Pause();
Fai( Arrived, -1 );
} // for
return NULL;
} // Worker
void __attribute__((noinline)) ctor() {
} // ctor
void __attribute__((noinline)) dtor() {
} // dtor
// Local Variables: //
// tab-width: 4 //
// compile-command: "gcc -Wall -Wextra -std=gnu11 -O3 -DNDEBUG -fno-reorder-functions -DPIN -DAlgorithm=MCSK42 Harness.c -lpthread -lm -D`hostname` -DCFMT -DCNT=0" //
// End: //