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,
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
42
44{
45 const uint32_t prev = semaphore_handle_->count.fetch_add(1, std::memory_order_release);
46 if (prev == 0)
47 {
48 (void)FutexWake(&semaphore_handle_->count, 1);
49 }
50}
51
52ErrorCode Semaphore::Wait(uint32_t timeout)
53{
54 const uint64_t deadline_ms =
55 (timeout == UINT32_MAX) ? UINT64_MAX : (MonotonicTime::NowMilliseconds() + timeout);
56
57 while (true)
58 {
59 uint32_t current = semaphore_handle_->count.load(std::memory_order_acquire);
60
61 while (current > 0)
62 {
63 if (semaphore_handle_->count.compare_exchange_weak(current, current - 1U,
64 std::memory_order_acq_rel,
65 std::memory_order_relaxed))
66 {
67 return ErrorCode::OK;
68 }
69 }
70
71 timespec ts = {};
72 timespec* ts_ptr = nullptr;
73 if (timeout != UINT32_MAX)
74 {
75 const uint32_t remaining_ms = MonotonicTime::RemainingMilliseconds(deadline_ms);
76 if (remaining_ms == 0)
77 {
78 return ErrorCode::TIMEOUT;
79 }
80 ts = MonotonicTime::RelativeFromMilliseconds(remaining_ms);
81 ts_ptr = &ts;
82 }
83
84 const int ans = FutexWait(&semaphore_handle_->count, 0, ts_ptr);
85 if (ans == 0 || errno == EAGAIN || errno == EINTR)
86 {
87 continue;
88 }
89
90 if (errno == ETIMEDOUT)
91 {
92 return ErrorCode::TIMEOUT;
93 }
94
95 return ErrorCode::FAILED;
96 }
97}
98
100{
101 UNUSED(in_isr);
102 Post();
103}
104
106{
107 return semaphore_handle_->count.load(std::memory_order_acquire);
108}
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:99
~Semaphore()
析构信号量对象,释放资源 Destroys the semaphore object and releases resources
Definition semaphore.cpp:41
libxr_semaphore_handle semaphore_handle_
信号量句柄 Semaphore handle
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:52
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ TIMEOUT
超时 | Timeout
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful