Xyris  0.5
Semaphore.cpp
Go to the documentation of this file.
1 /**
2  * @file semaphore.cpp
3  * @author Keeton Feavel ([email protected])
4  * @brief
5  * @version 0.3
6  * @date 2020-08-28
7  *
8  * @copyright Copyright the Xyris Contributors (c) 2020
9  *
10  */
11 #include <Locking/Semaphore.hpp>
12 
13 // Can't make this an inline function due to compiler errors with failure_memorder
14 // being too strong. Likely due to the fact that it doesn't know the value at compile time.
15 #define COMPARE_EXCHANGE(curVal, failure_memorder) __atomic_compare_exchange_n( \
16  &m_count, \
17  &curVal, \
18  curVal - 1, \
19  false, \
20  __ATOMIC_RELEASE, \
21  failure_memorder)
22 
23 Semaphore::Semaphore(uint32_t val, bool share, const char* name)
24  : m_isShared(share)
25  , m_count(val)
26 {
27  m_taskSync.dbg_name = name;
28  tasks_sync_init(&m_taskSync);
29 }
30 
32 {
33  uint32_t curVal = count();
34  do {
35  while (curVal == 0) {
37  curVal = count();
38  }
39  // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster.
40  } while (!COMPARE_EXCHANGE(curVal, __ATOMIC_RELAXED));
41 
42  return true;
43 }
44 
46 {
47  uint32_t curVal = count();
48  do {
49  if (curVal == 0) {
50  return false;
51  }
52  // We need to fail on an Atomic Acquire Release because it will fail less often (i.e. fewer loop iterations)
53  } while (!COMPARE_EXCHANGE(curVal, __ATOMIC_ACQUIRE));
54 
55  return true;
56 }
57 
58 bool Semaphore::timeWait(const uint32_t* usec)
59 {
60  // TODO: Add the timer functionality here.
61  (void)usec;
62  uint32_t curVal = count();
63  do {
64  while (curVal == 0) {
65  curVal = count();
66  }
67  // Fail using atomic relaxed because it may allow us to get to the "waiting" state faster.
68  } while (!COMPARE_EXCHANGE(curVal, __ATOMIC_ACQUIRE));
69 
70  return true;
71 }
72 
74 {
75  __atomic_fetch_add(&m_count, 1, __ATOMIC_RELEASE);
77 
78  return true;
79 }
80 
81 uint32_t Semaphore::count()
82 {
83  uint32_t ret = 0;
84  __atomic_load(&m_count, &ret, __ATOMIC_ACQUIRE);
85 
86  return ret;
87 }
Semaphore::timeWait
bool timeWait(const uint32_t *usec)
Wait on the semaphore for a set duration of time.
Definition: Semaphore.cpp:58
Semaphore::Semaphore
Semaphore(uint32_t val, bool share, const char *name=nullptr)
Initializes a semaphore struct using the values defined. Semaphores are used in order to maintain mut...
Definition: Semaphore.cpp:23
Semaphore::post
bool post()
Post to the semaphore.
Definition: Semaphore.cpp:73
Semaphore::count
uint32_t count()
Atomically get the semaphore's current counter value.
Definition: Semaphore.cpp:81
Semaphore::m_count
uint32_t m_count
Definition: Semaphore.hpp:68
COMPARE_EXCHANGE
#define COMPARE_EXCHANGE(curVal, failure_memorder)
Definition: Semaphore.cpp:15
task_sync::dbg_name
const char * dbg_name
Definition: tasks.hpp:58
Semaphore::m_taskSync
struct task_sync m_taskSync
Definition: Semaphore.hpp:69
Semaphore.hpp
tasks_sync_unblock
void tasks_sync_unblock(struct task_sync *ts)
Definition: tasks.cpp:575
TASK_ONLY
#define TASK_ONLY
Definition: tasks.hpp:46
Semaphore::tryWait
bool tryWait()
Check if the semaphore is available. If unavailable, return immediately, otherwise wait on the semaph...
Definition: Semaphore.cpp:45
tasks_sync_block
void tasks_sync_block(struct task_sync *ts)
Definition: tasks.cpp:560
Semaphore::wait
bool wait()
Wait for the semaphore to become available.
Definition: Semaphore.cpp:31