Block-Structured AMR Software Framework
AMReX_BlockMutex.H
Go to the documentation of this file.
1 #ifndef AMREX_BLOCK_MUTEX_H_
2 #define AMREX_BLOCK_MUTEX_H_
3 #include <AMReX_Config.H>
4 
5 #include <AMReX_Gpu.H>
6 
7 namespace amrex {
8 
9 #ifdef AMREX_USE_GPU
10 
11 struct BlockMutex
12 {
13  union state_t
14  {
15  struct II { int blockid; int count; } data;
16  unsigned long long ull;
17  };
18 
20  static constexpr state_t FreeState () noexcept {
21  return state_t{{-1,0}};
22  }
23 
24  static void init_states (state_t* state, int N) noexcept;
25 
26  explicit BlockMutex (int N) noexcept;
27 
28  ~BlockMutex ();
29 
30  void operator= (BlockMutex const&) = delete;
31 
33  void lock (int i) noexcept {
34 #ifdef AMREX_USE_SYCL
35 // xxxxx SYCL todo
37 #else
38  int blockid = blockIdx.z*blockDim.x*blockDim.y + blockIdx.y*blockDim.x + blockIdx.x;
39  state_t old = m_state[i];
40  state_t assumed;
41  do {
42  assumed = old;
43  state_t val;
44  val.data.blockid = blockid;
45  if (assumed.data.blockid == blockid) {
46  // Already locked by another thread in this block. Need to ++count.
47  val.data.count = assumed.data.count + 1;
48  } else {
49  // Currently unlocked or locked by another block. Need to lock.
50  val.data.count = 1;
51  assumed = FreeState();
52  }
53  old.ull = atomicCAS((unsigned long long*)(m_state+i), assumed.ull, val.ull);
54  } while (assumed.ull != old.ull);
55 #endif
56  }
57 
59  void unlock (int i) noexcept {
60 #ifdef AMREX_USE_SYCL
61 // xxxxx SYCL todo
63 #else
64  state_t old = m_state[i];
65  state_t assumed;
66  do {
67  assumed = old;
68  state_t val;
69  if (assumed.data.count == 1) {
70  // Need to unlock
71  val = FreeState();
72  } else {
73  // --count, but do NOT unlock
74  val = assumed;
75  --val.data.count;
76  }
77  old.ull = atomicCAS((unsigned long long*)(m_state+i), assumed.ull, val.ull);
78  } while (assumed.ull != old.ull);
79 #endif
80  }
81 
82 private:
83 
84  int m_nstates;
86 };
87 #endif
88 }
89 #endif
#define AMREX_FORCE_INLINE
Definition: AMReX_Extension.H:119
#define AMREX_GPU_DEVICE
Definition: AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition: AMReX_GpuQualifiers.H:20
Definition: AMReX_Amr.cpp:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition: AMReX.H:111
Definition: AMReX_BlockMutex.H:15
int blockid
Definition: AMReX_BlockMutex.H:15
int count
Definition: AMReX_BlockMutex.H:15
Definition: AMReX_BlockMutex.H:12
static constexpr AMREX_GPU_HOST_DEVICE state_t FreeState() noexcept
Definition: AMReX_BlockMutex.H:20
~BlockMutex()
Definition: AMReX_BlockMutex.cpp:34
void operator=(BlockMutex const &)=delete
int m_nstates
Definition: AMReX_BlockMutex.H:84
BlockMutex(int N) noexcept
Definition: AMReX_BlockMutex.cpp:21
state_t * m_state
Definition: AMReX_BlockMutex.H:85
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void unlock(int i) noexcept
Definition: AMReX_BlockMutex.H:59
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void lock(int i) noexcept
Definition: AMReX_BlockMutex.H:33
static void init_states(state_t *state, int N) noexcept
Definition: AMReX_BlockMutex.cpp:7
Definition: AMReX_BlockMutex.H:14
struct amrex::BlockMutex::state_t::II data
unsigned long long ull
Definition: AMReX_BlockMutex.H:16