libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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,
21 const struct timespec* timeout)
22{
23 return static_cast<int>(syscall(SYS_futex, reinterpret_cast<uint32_t*>(word),
24 FUTEX_WAIT, expected, timeout, nullptr, 0));
25}
26
27int FutexWake(std::atomic<uint32_t>* word, int count)
28{
29 return static_cast<int>(syscall(SYS_futex, reinterpret_cast<uint32_t*>(word),
30 FUTEX_WAKE, count, nullptr, nullptr, 0));
31}
32
33} // namespace
34
35Semaphore::Semaphore(uint32_t init_count)
36 : semaphore_handle_(new libxr_linux_futex_semaphore)
37{
38 semaphore_handle_->count.store(init_count, std::memory_order_release);
39}
40
41Semaphore::~Semaphore() { delete semaphore_handle_; }
42
44{
45 (void)semaphore_handle_->count.fetch_add(1, std::memory_order_release);
46 (void)FutexWake(&semaphore_handle_->count, 1);
47}
48
49ErrorCode Semaphore::Wait(uint32_t timeout)
50{
51 const uint64_t deadline_ms =
52 (timeout == UINT32_MAX) ? UINT64_MAX : (MonotonicTime::NowMilliseconds() + timeout);
53
54 while (true)
55 {
56 uint32_t current = semaphore_handle_->count.load(std::memory_order_acquire);
57
58 while (current > 0)
59 {
60 if (semaphore_handle_->count.compare_exchange_weak(current, current - 1U,
61 std::memory_order_acq_rel,
62 std::memory_order_relaxed))
63 {
64 return ErrorCode::OK;
65 }
66 }
67
68 timespec ts = {};
69 timespec* ts_ptr = nullptr;
70 if (timeout != UINT32_MAX)
71 {
72 const uint32_t remaining_ms = MonotonicTime::RemainingMilliseconds(deadline_ms);
73 if (remaining_ms == 0)
74 {
75 return ErrorCode::TIMEOUT;
76 }
77 ts = MonotonicTime::RelativeFromMilliseconds(remaining_ms);
78 ts_ptr = &ts;
79 }
80
81 const int ans = FutexWait(&semaphore_handle_->count, 0, ts_ptr);
82 if (ans == 0 || errno == EAGAIN || errno == EINTR)
83 {
84 continue;
85 }
86
87 if (errno == ETIMEDOUT)
88 {
89 return ErrorCode::TIMEOUT;
90 }
91
92 return ErrorCode::FAILED;
93 }
94}
95
97{
98 UNUSED(in_isr);
99 Post();
100}
101
103{
104 return semaphore_handle_->count.load(std::memory_order_acquire);
105}
void Post()
释放(增加)信号量 Releases (increments) the semaphore
Definition semaphore.cpp:43
void PostFromCallback(bool in_isr)
从中断回调中释放(增加)信号量 Releases (increments) the semaphore from an ISR (Interrupt Service Routine)
Definition semaphore.cpp:96
~Semaphore()
析构信号量对象,释放资源 Destroys the semaphore object and releases resources
Definition semaphore.cpp:41
Semaphore(uint32_t init_count=0)
构造一个信号量对象 Constructs a semaphore object
Definition semaphore.cpp:35
size_t Value()
获取当前信号量的值 Gets the current value of the semaphore
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:49
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ TIMEOUT
超时 / Timeout
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful