libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
semaphore.cpp
1#include "semaphore.hpp"
2
3#include <linux/futex.h>
4#include <sys/syscall.h>
5#include <time.h>
6#include <unistd.h>
7
8#include <atomic>
9#include <cerrno>
10#include <cstddef>
11
12#include "libxr_def.hpp"
13#include "monotonic_time.hpp"
14
15using namespace LibXR;
16
17namespace
18{
19
20int FutexWait(std::atomic<uint32_t>* word, uint32_t expected, const struct timespec* timeout)
21{
22 return static_cast<int>(syscall(SYS_futex, reinterpret_cast<uint32_t*>(word), FUTEX_WAIT,
23 expected, timeout, nullptr, 0));
24}
25
26int FutexWake(std::atomic<uint32_t>* word, int count)
27{
28 return static_cast<int>(syscall(SYS_futex, reinterpret_cast<uint32_t*>(word), FUTEX_WAKE,
29 count, nullptr, nullptr, 0));
30}
31
32} // namespace
33
34Semaphore::Semaphore(uint32_t init_count) : semaphore_handle_(new libxr_linux_futex_semaphore)
35{
36 semaphore_handle_->count.store(init_count, std::memory_order_release);
37}
38
43
45{
46 const uint32_t prev = semaphore_handle_->count.fetch_add(1, std::memory_order_release);
47 if (prev == 0)
48 {
49 (void)FutexWake(&semaphore_handle_->count, 1);
50 }
51}
52
53ErrorCode Semaphore::Wait(uint32_t timeout)
54{
55 const uint64_t deadline_ms =
56 (timeout == UINT32_MAX) ? UINT64_MAX : (MonotonicTime::NowMilliseconds() + timeout);
57
58 while (true)
59 {
60 uint32_t current = semaphore_handle_->count.load(std::memory_order_acquire);
61
62 while (current > 0)
63 {
64 if (semaphore_handle_->count.compare_exchange_weak(current, current - 1U,
65 std::memory_order_acq_rel,
66 std::memory_order_relaxed))
67 {
68 return ErrorCode::OK;
69 }
70 }
71
72 timespec ts = {};
73 timespec* ts_ptr = nullptr;
74 if (timeout != UINT32_MAX)
75 {
76 const uint32_t remaining_ms = MonotonicTime::RemainingMilliseconds(deadline_ms);
77 if (remaining_ms == 0)
78 {
79 return ErrorCode::TIMEOUT;
80 }
81 ts = MonotonicTime::RelativeFromMilliseconds(remaining_ms);
82 ts_ptr = &ts;
83 }
84
85 const int ans = FutexWait(&semaphore_handle_->count, 0, ts_ptr);
86 if (ans == 0 || errno == EAGAIN || errno == EINTR)
87 {
88 continue;
89 }
90
91 if (errno == ETIMEDOUT)
92 {
93 return ErrorCode::TIMEOUT;
94 }
95
96 return ErrorCode::FAILED;
97 }
98}
99
101{
102 UNUSED(in_isr);
103 Post();
104}
105
107{
108 return semaphore_handle_->count.load(std::memory_order_acquire);
109}
void Post()
释放(增加)信号量 Releases (increments) the semaphore
Definition semaphore.cpp:44
void PostFromCallback(bool in_isr)
从中断回调中释放(增加)信号量 Releases (increments) the semaphore from an ISR (Interrupt Service Routine)
~Semaphore()
析构信号量对象,释放资源 Destroys the semaphore object and releases resources
Definition semaphore.cpp:39
libxr_semaphore_handle semaphore_handle_
信号量句柄 Semaphore handle
Semaphore(uint32_t init_count=0)
构造一个信号量对象 Constructs a semaphore object
Definition semaphore.cpp:34
size_t Value()
获取当前信号量的值 Gets the current value of the semaphore
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:53
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
Definition libxr_def.hpp:64
@ TIMEOUT
超时 | Timeout
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful