SimpleKernel 1.17.0
Loading...
Searching...
No Matches
spinlock.hpp
Go to the documentation of this file.
1
5#pragma once
6
7#include <cpu_io.h>
8
9#include <atomic>
10#include <concepts>
11#include <cstddef>
12#include <limits>
13
14#include "expected.hpp"
15#include "kernel_log.hpp"
16#include "kstd_cstdio"
17
27class SpinLock {
28 public:
30 const char* name{"unnamed"};
31
36 [[nodiscard]] __always_inline auto Lock() -> Expected<void> {
37 auto intr_enable = cpu_io::GetInterruptStatus();
39
40 // 先尝试获取锁
41 while (locked_.test_and_set(std::memory_order_acquire)) {
42 // 在等待时检查是否是当前核心持有锁(递归锁检测)
43 if (core_id_.load(std::memory_order_acquire) ==
45 // 递归锁定,恢复中断状态并返回失败
46 if (intr_enable) {
48 }
49 // klog::Err("spinlock {}: {} recursive lock detected.",
50 // cpu_io::GetCurrentCoreId(), name);
51 return std::unexpected(Error{ErrorCode::kSpinLockRecursiveLock});
52 }
54 }
55
56 // 获取锁成功后立即设置 core_id_
57 core_id_.store(cpu_io::GetCurrentCoreId(), std::memory_order_release);
58 saved_intr_enable_ = intr_enable;
59 return {};
60 }
61
66 [[nodiscard]] __always_inline auto UnLock() -> Expected<void> {
67 if (!IsLockedByCurrentCore()) {
68 // klog::Err("spinlock {}: {} unlock by non-owner detected.",
69 // cpu_io::GetCurrentCoreId(), name);
70 return std::unexpected(Error{ErrorCode::kSpinLockNotOwned});
71 }
72
73 // 先重置 core_id_,再释放锁
74 core_id_.store(std::numeric_limits<size_t>::max(),
75 std::memory_order_release);
76 locked_.clear(std::memory_order_release);
77
80 }
81 return {};
82 }
83
86
92 explicit SpinLock(const char* _name) : name(_name) {}
93
94 SpinLock() = default;
95 SpinLock(const SpinLock&) = delete;
96 SpinLock(SpinLock&&) = default;
97 auto operator=(const SpinLock&) -> SpinLock& = delete;
98 auto operator=(SpinLock&&) -> SpinLock& = default;
99 ~SpinLock() = default;
101
102 protected:
104 std::atomic_flag locked_{ATOMIC_FLAG_INIT};
106 std::atomic<size_t> core_id_{std::numeric_limits<size_t>::max()};
109
115 __always_inline auto IsLockedByCurrentCore() -> bool {
116 return locked_.test(std::memory_order_acquire) &&
117 (core_id_.load(std::memory_order_acquire) ==
119 }
120};
121
126template <typename Mutex>
127 requires requires(Mutex& m) {
128 { m.Lock() } -> std::same_as<Expected<void>>;
129 { m.UnLock() } -> std::same_as<Expected<void>>;
130 }
132 public:
134
137
142 explicit LockGuard(mutex_type& mutex) : mutex_(mutex) {
143 mutex_.Lock().or_else([&](auto&& err) {
144 char core_buf[4] = {};
146 size_t pos = 0;
147 if (core_id == 0) {
148 core_buf[pos++] = '0';
149 } else {
150 char tmp[4] = {};
151 size_t tmp_pos = 0;
152 while (core_id > 0 && tmp_pos < sizeof(tmp)) {
153 tmp[tmp_pos++] = static_cast<char>('0' + (core_id % 10));
154 core_id /= 10;
155 }
156 while (tmp_pos > 0) {
157 core_buf[pos++] = tmp[--tmp_pos];
158 }
159 }
160 core_buf[pos] = '\0';
161 klog::RawPut("PANIC: LockGuard failed to acquire lock '");
163 klog::RawPut("' on core ");
164 klog::RawPut(core_buf);
165 klog::RawPut(": ");
166 klog::RawPut(err.message());
167 klog::RawPut("\n");
168 while (true) {
170 }
171 return Expected<void>{};
172 });
173 }
174
179 mutex_.UnLock().or_else([&](auto&& err) {
180 char core_buf[4] = {};
182 size_t pos = 0;
183 if (core_id == 0) {
184 core_buf[pos++] = '0';
185 } else {
186 char tmp[4] = {};
187 size_t tmp_pos = 0;
188 while (core_id > 0 && tmp_pos < sizeof(tmp)) {
189 tmp[tmp_pos++] = static_cast<char>('0' + (core_id % 10));
190 core_id /= 10;
191 }
192 while (tmp_pos > 0) {
193 core_buf[pos++] = tmp[--tmp_pos];
194 }
195 }
196 core_buf[pos] = '\0';
197 klog::RawPut("PANIC: LockGuard failed to release lock '");
199 klog::RawPut("' on core ");
200 klog::RawPut(core_buf);
201 klog::RawPut(": ");
202 klog::RawPut(err.message());
203 klog::RawPut("\n");
204 while (true) {
206 }
207 return Expected<void>{};
208 });
209 }
210
211 LockGuard() = delete;
212 LockGuard(const LockGuard&) = delete;
213 LockGuard(LockGuard&&) = delete;
214 auto operator=(const LockGuard&) -> LockGuard& = delete;
215 auto operator=(LockGuard&&) -> LockGuard& = delete;
217
218 private:
220};
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
LockGuard(const LockGuard &)=delete
mutex_type & mutex_
Definition spinlock.hpp:219
auto operator=(const LockGuard &) -> LockGuard &=delete
LockGuard()=delete
LockGuard(mutex_type &mutex)
构造函数,自动获取锁
Definition spinlock.hpp:142
auto operator=(LockGuard &&) -> LockGuard &=delete
LockGuard(LockGuard &&)=delete
~LockGuard()
析构函数,自动释放锁
Definition spinlock.hpp:178
互斥锁(Mutex)
Definition mutex.hpp:30
const char * name
锁的名称
Definition mutex.hpp:33
auto Lock() -> Expected< void >
获取锁(阻塞)
Definition mutex.cpp:11
auto UnLock() -> Expected< void >
释放锁
Definition mutex.cpp:41
自旋锁
Definition spinlock.hpp:27
std::atomic_flag locked_
是否 Lock
Definition spinlock.hpp:104
__always_inline auto Lock() -> Expected< void >
获得锁
Definition spinlock.hpp:36
auto operator=(const SpinLock &) -> SpinLock &=delete
__always_inline auto IsLockedByCurrentCore() -> bool
检查当前 core 是否获得此锁
Definition spinlock.hpp:115
SpinLock(SpinLock &&)=default
SpinLock(const SpinLock &)=delete
~SpinLock()=default
SpinLock(const char *_name)
构造函数
Definition spinlock.hpp:92
auto operator=(SpinLock &&) -> SpinLock &=default
const char * name
自旋锁名称
Definition spinlock.hpp:30
std::atomic< size_t > core_id_
获得此锁的 core_id
Definition spinlock.hpp:106
SpinLock()=default
bool saved_intr_enable_
保存的中断状态
Definition spinlock.hpp:108
__always_inline auto UnLock() -> Expected< void >
释放锁
Definition spinlock.hpp:66
@ kSpinLockRecursiveLock
@ kSpinLockNotOwned
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
void DisableInterrupt()
Definition cpu_io.h:41
bool GetInterruptStatus()
Definition cpu_io.h:48
void Pause()
Definition cpu_io.h:20
void EnableInterrupt()
Definition cpu_io.h:34
__always_inline auto RawPut(const char *msg) -> void
绕过队列直接输出至串口(用于 panic 路径)
size_t core_id
核心 ID
Definition per_cpu.hpp:1
错误类型,用于 std::expected
Definition expected.hpp:343