Zero  0.1.0
tatas.h
Go to the documentation of this file.
1 #ifndef __TATAS_H
2 #define __TATAS_H
3 
4 #include "AtomicCounter.hpp"
5 #include "w_defines.h"
6 
7 #if MUTRACE_ENABLED_H
8 #include <MUTrace/mutrace.h>
9 #endif // MUTRACE_ENABLED_H
10 
25 struct tatas_lock {
27  enum {
28  NOBODY = 0
29  };
30 
31  typedef union {
32  pthread_t handle;
33 #if SIZEOF_PTHREAD_T == 8
34  uint64_t bits;
35 #elif SIZEOF_PTHREAD_T == 0
36 #error Configuration could not determine size of pthread_t. Fix configure.ac.
37 #else
38 #error Configuration determined size of pthread_t is unexpected. Fix sthread.h.
39 #endif
40  } holder_type_t;
41 
42  volatile holder_type_t _holder;
45 #ifdef MUTRACE_ENABLED_H
46  MUTRACE_PROFILE_MUTEX_CONSTRUCTOR(tatas_lock) { _holder.bits=NOBODY; }
47 #else
48 
50  _holder.bits = NOBODY;
51  }
52 
53 #endif
54 
55 private:
56  // CC mangles this as __1cKtatas_lockEspin6M_v_
58  void spin() {
59  while (*&(_holder.handle)) {}
60  }
61 
62 public:
64  bool try_lock() {
65  holder_type_t tid = {pthread_self()};
66  bool success = false;
67  uint64_t old_holder = NOBODY;
68  if (lintel::unsafe::atomic_compare_exchange_strong(const_cast<uint64_t*>(&_holder.bits), &old_holder,
69  tid.bits)) {
71  success = true;
72  }
73  return success;
74  }
75 
77 #ifdef MUTRACE_ENABLED_H
78  MUTRACE_PROFILE_MUTEX_LOCK_VOID(tatas_lock, void, acquire, try_lock)
79 #else
80 
81  void acquire()
82 #endif
83  {
84  w_assert1(!is_mine());
85  holder_type_t tid = {pthread_self()};
86  uint64_t old_holder = NOBODY;
87  do {
88  spin();
89  old_holder = NOBODY; // a CAS that fails overwrites old_holder with the current holder
90  } while (!lintel::unsafe::atomic_compare_exchange_strong(const_cast<uint64_t*>(&_holder.bits), &old_holder,
91  tid.bits));
93  w_assert1(is_mine());
94  }
95 
97 #ifdef MUTRACE_ENABLED_H
98  MUTRACE_PROFILE_MUTEX_UNLOCK_VOID(tatas_lock, void, release)
99 #else
100 
101  void release()
102 #endif
103  {
105  w_assert1(is_mine()); // moved after the fence
106  _holder.bits = NOBODY;
107 #if W_DEBUG_LEVEL > 0
108  {
110  w_assert1(!is_mine());
111  }
112 #endif
113  }
114 
116  bool is_mine() const {
117  return
118  pthread_equal(_holder.handle, pthread_self()) ? true : false;
119  }
120 
121 #undef CASFUNC
122 };
123 
126 public:
127  tataslock_critical_section(tatas_lock* lock) : _lock(lock) {
128  _lock->acquire();
129  }
130 
132  _lock->release();
133  }
134 
135 private:
137 };
138 
141 
142 #endif // __TATAS_H
void atomic_thread_fence(memory_order order)
Definition: AtomicCounter.hpp:223
bool is_mine() const
True if this thread is the lock holder.
Definition: tatas.h:116
void acquire()
Acquire the lock, spinning as long as necessary.
Definition: tatas.h:81
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
const size_t CACHELINE_TATAS_PADDING
Definition: tatas.h:140
tatas_lock * _lock
Definition: tatas.h:136
Header file for lintel::Atomic class.
~tataslock_critical_section()
Definition: tatas.h:131
void release()
Release the lock.
Definition: tatas.h:101
void spin()
spin until lock is free
Definition: tatas.h:58
tatas_lock()
Definition: tatas.h:49
A test-and-test-and-set spinlock.
Definition: tatas.h:25
Definition: AtomicCounter.hpp:114
Definition: tatas.h:125
bool try_lock()
Try to acquire the lock immediately.
Definition: tatas.h:64
tataslock_critical_section(tatas_lock *lock)
Definition: tatas.h:127
bool atomic_compare_exchange_strong(T *object, T *expected, C desired)
Definition: AtomicCounter.hpp:401
Definition: AtomicCounter.hpp:113
const size_t CACHELINE_SIZE
CPU Cache line size in bytes.
Definition: w_defines.h:183