LSLab
warp_mutex.h
Go to the documentation of this file.
1 
5 #include "lslab.h"
6 #include <atomic>
7 #include <cuda/atomic>
8 
9 #pragma once
10 
11 namespace lslab {
12 
13 struct warp_mutex {
14 
15  warp_mutex() : l(0) {}
16 
17  LSLAB_DEVICE void lock() {
18  if(threadIdx.x % 32 == 0) {
19  int expect = 0;
20  while(!l.compare_exchange_strong(expect,-1, cuda::std::memory_order_acquire)) {
21  expect = 0;
22  }
23  }
24  __syncwarp();
25  }
26 
27  LSLAB_DEVICE void unlock() {
28  if(threadIdx.x % 32 == 0) {
29  l.store(0, cuda::std::memory_order_release);
30  }
31  }
32 
33  LSLAB_DEVICE void shared_lock() {
34  if(threadIdx.x % 32 == 0) {
35  while(true) {
36  int pred = l.load(cuda::std::memory_order_relaxed);
37  if(pred != -1 && l.compare_exchange_strong(pred, pred + 1, cuda::std::memory_order_acquire)) {
38  break;
39  }
40  }
41  }
42  __syncwarp();
43  }
44 
45  LSLAB_DEVICE int status() {
46  return l.load();
47  }
48 
49  LSLAB_DEVICE void shared_unlock() {
50  if(threadIdx.x % 32 == 0) {
51  l.fetch_add(-1, cuda::std::memory_order_release);
52  }
53  }
54 
55  union {
56  alignas(32) char _[32];
57  cuda::std::atomic<int> l;
58  };
59 };
60 
61 template<typename T>
63  LSLAB_DEVICE warp_unique_lock() : mtx(nullptr) {}
64 
65  LSLAB_DEVICE warp_unique_lock(T& mtx_) : mtx(&mtx_) {
66  mtx->lock();
67  }
68 
69  LSLAB_DEVICE warp_unique_lock(const warp_unique_lock<T>&) = delete;
70 
71  LSLAB_DEVICE warp_unique_lock(warp_unique_lock<T>&& other) {
72  mtx = other.mtx;
73  other.mtx = nullptr;
74  }
75 
76  LSLAB_DEVICE warp_unique_lock& operator=(warp_unique_lock<T>&& other) {
77  if(mtx) mtx->unlock();
78  mtx = other.mtx;
79  other.mtx = nullptr;
80  }
81 
82  LSLAB_DEVICE ~warp_unique_lock() {
83  if(mtx) mtx->unlock();
84  }
85 
86  T* mtx;
87 };
88 
89 template<typename T>
91 
92  LSLAB_DEVICE warp_shared_lock() : mtx(nullptr) {}
93 
94  LSLAB_DEVICE warp_shared_lock(const warp_shared_lock<T>&) = delete;
95 
96  LSLAB_DEVICE warp_shared_lock(warp_shared_lock<T>&& other) {
97  mtx = other.mtx;
98  other.mtx = nullptr;
99  }
100 
101  LSLAB_DEVICE warp_shared_lock& operator=(warp_shared_lock<T>&& other) {
102  if(mtx) mtx->shared_unlock();
103  mtx = other.mtx;
104  other.mtx = nullptr;
105  }
106 
107  LSLAB_DEVICE warp_shared_lock(T& mtx_) : mtx(&mtx_) {
108  mtx->shared_lock();
109  }
110 
111  LSLAB_DEVICE ~warp_shared_lock() {
112  if(mtx) mtx->shared_unlock();
113  }
114 
115  T* mtx;
116 };
117 
118 template<typename T>
120 
121  LSLAB_DEVICE warp_noop_lock() : mtx(nullptr) {}
122 
123  LSLAB_DEVICE warp_noop_lock(const warp_noop_lock<T>&) = delete;
124 
125  LSLAB_DEVICE warp_noop_lock(warp_noop_lock<T>&& other) {
126  }
127 
128  LSLAB_DEVICE warp_noop_lock& operator=(warp_noop_lock<T>&& other) {
129  }
130 
131  LSLAB_DEVICE warp_noop_lock(T& mtx_) : mtx(&mtx_) {
132  }
133 
134  LSLAB_DEVICE ~warp_noop_lock() {
135  }
136 
137  T* mtx;
138 };
139 
140 }
Definition: warp_mutex.h:13
Definition: warp_mutex.h:119
Definition: warp_mutex.h:90
Definition: warp_mutex.h:62