Skip to content

Commit cc7f96f

Browse files
committed
feat: mutex
Signed-off-by: Niu Zhihong <zhihong@nzhnb.com>
1 parent b2380f5 commit cc7f96f

3 files changed

Lines changed: 72 additions & 328 deletions

File tree

tests/system_test/main.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@ auto main(int argc, const char** argv) -> int {
121121

122122
klog::info << "Hello SimpleKernel\n";
123123

124-
// 运行 Mutex 测试
125-
MutexTest::RunTest();
126-
127124
// 主核运行所有测试(包括多核测试)
128125
run_tests_main();
129126

tests/system_test/mutex_test.cpp

Lines changed: 1 addition & 269 deletions
Original file line numberDiff line numberDiff line change
@@ -10,276 +10,8 @@
1010
#include "cpu_io.h"
1111
#include "singleton.hpp"
1212
#include "sk_stdio.h"
13+
#include "sk_string.h"
1314
#include "spinlock.hpp"
1415
#include "syscall.hpp"
1516
#include "system_test.h"
1617
#include "task_manager.hpp"
17-
18-
namespace {
19-
20-
// 测试用的共享变量
21-
static std::atomic<int> shared_counter{0};
22-
static std::atomic<int> finished_tasks{0};
23-
static Mutex* test_mutex = nullptr;
24-
25-
/**
26-
* @brief 测试基本的 Lock/UnLock 功能
27-
*/
28-
auto test_basic_lock() -> bool {
29-
sk_printf("Running test_basic_lock...\n");
30-
31-
Mutex mutex("basic_test");
32-
EXPECT_TRUE(mutex.Lock(), "Basic lock failed");
33-
EXPECT_TRUE(mutex.IsLockedByCurrentTask(),
34-
"IsLockedByCurrentTask failed after lock");
35-
EXPECT_TRUE(mutex.UnLock(), "Basic unlock failed");
36-
EXPECT_TRUE(!mutex.IsLockedByCurrentTask(),
37-
"IsLockedByCurrentTask failed after unlock");
38-
39-
sk_printf("test_basic_lock passed\n");
40-
return true;
41-
}
42-
43-
/**
44-
* @brief 测试递归加锁检测
45-
*/
46-
auto test_recursive_lock() -> bool {
47-
sk_printf("Running test_recursive_lock...\n");
48-
49-
Mutex mutex("recursive_test");
50-
EXPECT_TRUE(mutex.Lock(), "Lock failed in recursive test");
51-
52-
// 尝试递归获取锁应该失败
53-
if (mutex.Lock()) {
54-
sk_printf("FAIL: Recursive lock should return false\n");
55-
mutex.UnLock(); // 尝试恢复
56-
mutex.UnLock();
57-
return false;
58-
}
59-
60-
EXPECT_TRUE(mutex.UnLock(), "Unlock failed in recursive test");
61-
62-
// 再次解锁应该失败(未持有锁)
63-
if (mutex.UnLock()) {
64-
sk_printf("FAIL: Double unlock should return false\n");
65-
return false;
66-
}
67-
68-
sk_printf("test_recursive_lock passed\n");
69-
return true;
70-
}
71-
72-
/**
73-
* @brief 测试 TryLock 功能
74-
*/
75-
auto test_trylock() -> bool {
76-
sk_printf("Running test_trylock...\n");
77-
78-
Mutex mutex("trylock_test");
79-
80-
// 第一次 TryLock 应该成功
81-
EXPECT_TRUE(mutex.TryLock(), "First TryLock failed");
82-
EXPECT_TRUE(mutex.IsLockedByCurrentTask(), "TryLock didn't acquire lock");
83-
84-
// 再次 TryLock 应该失败(递归)
85-
if (mutex.TryLock()) {
86-
sk_printf("FAIL: Recursive TryLock should return false\n");
87-
mutex.UnLock();
88-
return false;
89-
}
90-
91-
EXPECT_TRUE(mutex.UnLock(), "UnLock after TryLock failed");
92-
93-
sk_printf("test_trylock passed\n");
94-
return true;
95-
}
96-
97-
/**
98-
* @brief 测试 LockGuard<Mutex> RAII
99-
*/
100-
auto test_mutex_guard() -> bool {
101-
sk_printf("Running test_mutex_guard...\n");
102-
103-
Mutex mutex("guard_test");
104-
105-
{
106-
LockGuard<Mutex> guard(mutex);
107-
EXPECT_TRUE(mutex.IsLockedByCurrentTask(), "LockGuard failed to lock");
108-
}
109-
// 作用域结束后应该自动解锁
110-
EXPECT_TRUE(!mutex.IsLockedByCurrentTask(), "LockGuard failed to unlock");
111-
112-
sk_printf("test_mutex_guard passed\n");
113-
return true;
114-
}
115-
116-
/**
117-
* @brief 测试多任务竞争互斥锁
118-
*/
119-
void mutex_contention_task(void* arg) {
120-
int task_id = *reinterpret_cast<int*>(arg);
121-
sk_printf("Task %d: started\n", task_id);
122-
123-
for (int i = 0; i < 100; ++i) {
124-
// 获取互斥锁
125-
test_mutex->Lock();
126-
127-
// 临界区:增加共享计数器
128-
int old_value = shared_counter.load();
129-
// 模拟一些计算
130-
for (volatile int j = 0; j < 10; ++j) {
131-
;
132-
}
133-
shared_counter.store(old_value + 1);
134-
135-
// 释放互斥锁
136-
test_mutex->UnLock();
137-
}
138-
139-
sk_printf("Task %d: finished\n", task_id);
140-
finished_tasks.fetch_add(1);
141-
}
142-
143-
/**
144-
* @brief 测试多任务竞争场景
145-
*/
146-
auto test_mutex_contention() -> bool {
147-
sk_printf("Running test_mutex_contention...\n");
148-
149-
// 重置测试变量
150-
shared_counter = 0;
151-
finished_tasks = 0;
152-
153-
// 创建测试用的互斥锁
154-
static Mutex mutex("contention_test");
155-
test_mutex = &mutex;
156-
157-
// 创建多个任务竞争同一个锁
158-
constexpr int kNumTasks = 4;
159-
constexpr int kIterations = 100;
160-
static int task_ids[kNumTasks];
161-
162-
auto& task_manager = Singleton<TaskManager>::GetInstance();
163-
164-
for (int i = 0; i < kNumTasks; ++i) {
165-
task_ids[i] = i;
166-
auto* task = new TaskControlBlock("mutex_test_task", 10,
167-
mutex_contention_task, &task_ids[i]);
168-
task_manager.AddTask(task);
169-
}
170-
171-
// 等待所有任务完成
172-
sk_printf("Waiting for tasks to complete...\n");
173-
while (finished_tasks.load() < kNumTasks) {
174-
// 让出 CPU,让其他任务运行
175-
sys_yield();
176-
}
177-
178-
// 验证计数器值
179-
int expected = kNumTasks * kIterations;
180-
int actual = shared_counter.load();
181-
182-
if (actual != expected) {
183-
sk_printf("FAIL: Expected counter=%d, got %d\n", expected, actual);
184-
return false;
185-
}
186-
187-
sk_printf("test_mutex_contention passed (counter=%d)\n", actual);
188-
return true;
189-
}
190-
191-
/**
192-
* @brief 测试 LockGuard<Mutex> 在多任务场景下的使用
193-
*/
194-
void mutex_guard_task(void* arg) {
195-
int task_id = *reinterpret_cast<int*>(arg);
196-
sk_printf("Task %d: started (with guard)\n", task_id);
197-
198-
for (int i = 0; i < 100; ++i) {
199-
// 使用 RAII 风格的 LockGuard<Mutex>
200-
LockGuard<Mutex> guard(*test_mutex);
201-
202-
// 临界区
203-
int old_value = shared_counter.load();
204-
for (volatile int j = 0; j < 10; ++j) {
205-
;
206-
}
207-
shared_counter.store(old_value + 1);
208-
// guard 在作用域结束时自动释放锁
209-
}
210-
211-
sk_printf("Task %d: finished (with guard)\n", task_id);
212-
finished_tasks.fetch_add(1);
213-
}
214-
215-
/**
216-
* @brief 测试 LockGuard<Mutex> 在多任务竞争场景
217-
*/
218-
auto test_mutex_guard_contention() -> bool {
219-
sk_printf("Running test_mutex_guard_contention...\n");
220-
221-
// 重置测试变量
222-
shared_counter = 0;
223-
finished_tasks = 0;
224-
225-
static Mutex mutex("guard_contention_test");
226-
test_mutex = &mutex;
227-
228-
constexpr int kNumTasks = 4;
229-
constexpr int kIterations = 100;
230-
static int task_ids[kNumTasks];
231-
232-
auto& task_manager = Singleton<TaskManager>::GetInstance();
233-
234-
for (int i = 0; i < kNumTasks; ++i) {
235-
task_ids[i] = i;
236-
auto* task = new TaskControlBlock("mutex_guard_test_task", 10,
237-
mutex_guard_task, &task_ids[i]);
238-
task_manager.AddTask(task);
239-
}
240-
241-
// 等待所有任务完成
242-
sk_printf("Waiting for guard tasks to complete...\n");
243-
while (finished_tasks.load() < kNumTasks) {
244-
sys_yield();
245-
}
246-
247-
// 验证计数器值
248-
int expected = kNumTasks * kIterations;
249-
int actual = shared_counter.load();
250-
251-
if (actual != expected) {
252-
sk_printf("FAIL: Expected counter=%d, got %d\n", expected, actual);
253-
return false;
254-
}
255-
256-
sk_printf("test_mutex_guard_contention passed (counter=%d)\n", actual);
257-
return true;
258-
}
259-
260-
} // namespace
261-
262-
namespace MutexTest {
263-
264-
void RunTest() {
265-
sk_printf("\n========== Mutex System Tests ==========\n");
266-
267-
bool all_passed = true;
268-
269-
all_passed &= test_basic_lock();
270-
all_passed &= test_recursive_lock();
271-
all_passed &= test_trylock();
272-
all_passed &= test_mutex_guard();
273-
all_passed &= test_mutex_contention();
274-
all_passed &= test_mutex_guard_contention();
275-
276-
if (all_passed) {
277-
sk_printf("\n[PASS] All Mutex tests passed!\n");
278-
} else {
279-
sk_printf("\n[FAIL] Some Mutex tests failed!\n");
280-
}
281-
282-
sk_printf("========== Mutex Tests Complete ==========\n\n");
283-
}
284-
285-
} // namespace MutexTest

0 commit comments

Comments
 (0)