-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathMCS.h
87 lines (69 loc) · 2.34 KB
/
MCS.h
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
#pragma once
#include <stdbool.h>
typedef struct mcs_node {
#ifndef ATOMIC
struct mcs_node * volatile next;
#else
_Atomic(struct mcs_node *) next;
#endif // ! ATOMIC
VTYPE spin;
} MCS_node CALIGN;
#ifndef ATOMIC
typedef MCS_node * MCS_lock;
#else
typedef _Atomic(MCS_node *) MCS_lock;
#endif // ! ATOMIC
static inline void mcs_lock( MCS_lock * lock, MCS_node * node ) {
node->next = NULL;
#ifndef MCS_OPT1 // default option
node->spin = true; // alternative position and remove fence below
WO( Fence(); ); // 1
#endif // MCS_OPT1
MCS_node * prev = Fas( *lock, node );
if ( SLOWPATH( prev == NULL ) ) return; // no one on list ?
#ifdef MCS_OPT1
node->spin = true; // mark as waiting
WO( Fence(); ); // 2
#endif // MCS_OPT1
prev->next = node; // add to list of waiting threads
WO( Fence(); ); // 3
#ifndef MPAUSE
while ( node->spin == true ) Pause(); // busy wait on my spin variable
#else
MPause( node->spin, == true ); // busy wait on my spin variable
#endif // MPAUSE
WO( Fence(); ); // 4
} // mcs_lock
static inline void mcs_unlock( MCS_lock * lock, MCS_node * node ) {
WO( Fence(); ); // 5
#ifdef MCS_OPT2 // original, default option
if ( FASTPATH( node->next == NULL ) ) { // no one waiting ?
if ( SLOWPATH( Cas( *lock, node, NULL ) ) ) return; // Fence
#ifndef MPAUSE
while ( node->next == NULL ) Pause(); // busy wait until my node is modified
#else
MPause( node->next, == NULL ); // busy wait until my node is modified
#endif // MPAUSE
} // if
WO( Fence(); ); // 6
node->next->spin = false; // stop their busy wait
#else // Scott book Figure 4.8
MCS_node * succ = node->next;
if ( FASTPATH( succ == NULL ) ) { // no one waiting ?
// node is potentially at the tail of the MCS chain
if ( SLOWPATH( Cas( *lock, node, NULL ) ) ) return; // Fence
// Either a new thread arrived in the LD-CAS window above or fetched a false NULL
// as the successor has yet to store into node->next.
#ifndef MPAUSE
while ( (succ = node->next) == NULL ) Pause(); // busy wait until my node is modified
#else
MPauseS( succ =, node->next, == NULL ); // busy wait until my node is modified
#endif // MPAUSE
} // if
WO( Fence(); ); // 7
succ->spin = false;
#endif // MCS_OPT2
} // mcs_unlock
// Local Variables: //
// tab-width: 4 //
// End: //