The CDSSpec checker's benchmarks
[model-checker-benchmarks.git] / mcs-lock / mcs-lock.h
1 // mcs on stack
2
3 #ifndef _MCS_LOCK_H
4 #define _MCS_LOCK_H
5
6 #include <stdatomic.h>
7 #include <threads.h>
8 #include <unrelacy.h>
9
10 // Forward declaration
11 struct mcs_node;
12 struct mcs_mutex;
13
14 struct mcs_node {
15         std::atomic<mcs_node *> next;
16         std::atomic<int> gate;
17
18         mcs_node() {
19                 next.store(0);
20                 gate.store(0);
21         }
22 };
23
24 // C-callable interface
25 typedef void *CGuard;
26 void mcs_lock(mcs_mutex *mutex, CGuard guard);
27
28 void mcs_unlock(mcs_mutex *mutex, CGuard guard);
29
30 struct mcs_mutex {
31 public:
32         // tail is null when lock is not held
33         std::atomic<mcs_node *> m_tail;
34
35         mcs_mutex() {
36                 m_tail.store( NULL );
37         }
38         ~mcs_mutex() {
39                 RL_ASSERT( m_tail.load() == NULL );
40         }
41
42         class guard {
43         public:
44                 mcs_mutex * m_t;
45                 mcs_node    m_node; // node held on the stack
46                 
47                 // Call the wrapper (instrument every lock/unlock)
48                 guard(mcs_mutex * t) : m_t(t) { mcs_lock(t, this); }
49                 ~guard() { mcs_unlock(m_t, this); }
50         };
51
52         void lock(guard * I);
53
54         void unlock(guard * I);
55 };
56
57 #endif