SimpleKernel 1.17.0
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1
5#include <atomic>
6#include <cstdint>
7#include <new>
8
9#include "arch.h"
10#include "basic_info.hpp"
11#include "kernel.h"
12#include "kernel_log.hpp"
13#include "kstd_cstdio"
14#include "kstd_libcxx.h"
15#include "kstd_memory"
16#include "per_cpu.hpp"
17#include "spinlock.hpp"
18#include "syscall.hpp"
19#include "system_test.h"
21#include "task_manager.hpp"
22
23namespace {
24
25struct test_case {
26 const char* name;
27 bool (*func)(void);
28 bool is_smp_test = false;
29};
30
31constexpr size_t kTestCount = 18;
32
33std::array<test_case, kTestCount> test_cases = {
34 test_case{"ctor_dtor_test", ctor_dtor_test, false},
35 test_case{"spinlock_test", spinlock_test, true},
36 test_case{"memory_test", memory_test, false},
37 test_case{"virtual_memory_test", virtual_memory_test, false},
38 test_case{"interrupt_test", interrupt_test, false},
39 test_case{"fifo_scheduler_test", fifo_scheduler_test, false},
40 test_case{"rr_scheduler_test", rr_scheduler_test, false},
41 test_case{"cfs_scheduler_test", cfs_scheduler_test, false},
42 test_case{"idle_scheduler_test", idle_scheduler_test, false},
43 test_case{"thread_group_system_test", thread_group_system_test, false},
44 test_case{"wait_system_test", wait_system_test, false},
45 test_case{"clone_system_test", clone_system_test, false},
46 test_case{"exit_system_test", exit_system_test, false},
47 test_case{"ramfs_system_test", ramfs_system_test, false},
48 test_case{"fatfs_system_test", fatfs_system_test, false},
49 test_case{"mutex_test", mutex_test, false},
50 test_case{"kernel_task_test", kernel_task_test, false},
51 test_case{"user_task_test", user_task_test, false}};
52
53std::array<TestResult, kTestCount> test_results{};
54
55std::atomic<size_t> g_cores_ready{0};
56
57void test_thread_entry(void* arg) {
58 auto idx = reinterpret_cast<uint64_t>(arg);
59 auto& test = test_cases[idx];
60
61 klog::Info("[TEST] Starting: {}", test.name);
62
63 bool passed = test.func();
64
65 klog::Info("[TEST] Finished: {} — {}", test.name, passed ? "PASS" : "FAIL");
66
67 sys_exit(passed ? 0 : 1);
68}
69
70void print_test_summary() {
71 int passed = 0;
72 int failed = 0;
73 int timed_out = 0;
74
75 klog::Info("========================================");
76 klog::Info(" System Test Results");
77 klog::Info("========================================");
78
79 for (size_t i = 0; i < kTestCount; ++i) {
80 auto& r = test_results[i];
81 const char* tag = "???";
82
83 switch (r.status) {
85 tag = "PASS";
86 passed++;
87 break;
89 tag = "FAIL";
90 failed++;
91 break;
93 tag = "TIMEOUT";
94 timed_out++;
95 break;
97 tag = "TIMEOUT";
98 timed_out++;
99 break;
100 default:
101 tag = "SKIP";
102 break;
103 }
104
105 if (test_cases[i].is_smp_test) {
106 klog::Info(" [{}] {} (SMP, exit_code={})", tag, r.name, r.exit_code);
107 } else {
108 klog::Info(" [{}] {} (pid={}, exit_code={})", tag, r.name, r.pid,
109 r.exit_code);
110 }
111 }
112
113 int total = static_cast<int>(kTestCount);
114
115 klog::Info("========================================");
116 klog::Info(" Total: {} | Passed: {} | Failed: {} | Timeout: {}", total,
117 passed, failed, timed_out);
118 klog::Info("========================================");
119}
120
121void test_runner_entry(void* /*arg*/) {
122 auto& task_mgr = TaskManagerSingleton::instance();
123 auto* runner = task_mgr.GetCurrentTask();
124
125 // Phase 2: 为每个非 SMP 测试创建独立线程,建立父子关系
126 int thread_test_count = 0;
127
128 for (size_t i = 0; i < kTestCount; ++i) {
129 if (test_cases[i].is_smp_test) {
130 continue;
131 }
132
133 auto task = kstd::make_unique<TaskControlBlock>(
134 test_cases[i].name, 10, test_thread_entry, reinterpret_cast<void*>(i));
135
136 // Wait() requires parent-child relationship to collect exit status
137 task->aux->parent_pid = runner->pid;
138 task->aux->pgid = runner->aux->pgid;
139
140 test_results[i].pid = task->pid;
141 test_results[i].status = TestThreadStatus::kRunning;
142
143 task_mgr.AddTask(std::move(task));
144 thread_test_count++;
145 }
146
147 klog::Info("[RUNNER] Spawned {} test threads, collecting via Wait()...",
148 thread_test_count);
149
150 // Phase 3: 通过 Wait() 收集所有测试线程的退出状态
151 int collected = 0;
152 constexpr int kMaxWaitRetries = 1200; // 1200 * 50ms = 60s 超时
153 int retries = 0;
154
155 while (collected < thread_test_count && retries < kMaxWaitRetries) {
156 int status = 0;
157 auto wait_result =
158 task_mgr.Wait(static_cast<Pid>(-1), &status, true, false);
159
160 if (wait_result.has_value() && wait_result.value() > 0) {
161 Pid exited_pid = wait_result.value();
162
163 for (size_t i = 0; i < kTestCount; ++i) {
164 if (test_results[i].pid == static_cast<int64_t>(exited_pid)) {
165 test_results[i].exit_code = status;
166 test_results[i].status = (status == 0) ? TestThreadStatus::kPassed
168
169 klog::Info("[RUNNER] Collected: {} (pid={}, exit_code={}) — {}",
170 test_cases[i].name, exited_pid, status,
171 (status == 0) ? "PASS" : "FAIL");
172 break;
173 }
174 }
175
176 collected++;
177 } else {
178 (void)sys_sleep(50);
179 retries++;
180 }
181 }
182
183 for (size_t i = 0; i < kTestCount; ++i) {
184 if (test_cases[i].is_smp_test) {
185 continue;
186 }
187 if (test_results[i].status == TestThreadStatus::kPending ||
188 test_results[i].status == TestThreadStatus::kRunning) {
189 test_results[i].status = TestThreadStatus::kTimeout;
190 klog::Err("[RUNNER] Timeout: {} (pid={})", test_cases[i].name,
191 test_results[i].pid);
192 }
193 }
194
195 // Phase 4: 汇总打印
196 print_test_summary();
197
198 bool all_passed = true;
199 for (size_t i = 0; i < kTestCount; ++i) {
200 if (test_results[i].status != TestThreadStatus::kPassed) {
201 all_passed = false;
202 break;
203 }
204 }
205
206 QemuExit(all_passed);
207}
208
209void run_tests_smp() {
210 for (const auto& test : test_cases) {
211 if (test.is_smp_test) {
212 test.func();
213 }
214 }
215}
216
217auto main_smp(int argc, const char** argv) -> int {
219 ArchInitSMP(argc, argv);
221 InterruptInitSMP(argc, argv);
222 TaskManagerSingleton::instance().InitCurrentCore();
223 TimerInitSMP();
224 klog::Info("Hello SimpleKernel SMP");
225
226 g_cores_ready.fetch_add(1, std::memory_order_release);
227
228 run_tests_smp();
229
230 TaskManagerSingleton::instance().Schedule();
231
232 __builtin_unreachable();
233}
234
235} // namespace
236
237auto _start(int argc, const char** argv) -> void {
238 if (argv != nullptr) {
239 CppInit();
240 main(argc, argv);
241 } else {
242 main_smp(argc, argv);
243 }
244
245 while (true) {
247 }
248}
249
250auto main(int argc, const char** argv) -> int {
251 per_cpu::PerCpuArraySingleton::create();
253
254 ArchInit(argc, argv);
255 MemoryInit();
256 InterruptInit(argc, argv);
257 DeviceInit();
259
260 TaskManagerSingleton::create();
261 TaskManagerSingleton::instance().InitCurrentCore();
262
263 TimerInit();
264
266
267 DumpStack();
268
269 klog::Info("Hello SimpleKernel");
270
271 for (size_t i = 0; i < kTestCount; ++i) {
272 test_results[i].name = test_cases[i].name;
273 test_results[i].status = TestThreadStatus::kPending;
274 test_results[i].exit_code = -1;
275 test_results[i].pid = 0;
276 }
277
278 // Phase 1: SMP 测试同步运行(需要跨核屏障协调,必须在调度器启动前完成)
279 size_t expected_cores = BasicInfoSingleton::instance().core_count - 1;
280 klog::Info("[RUNNER] Waiting for {} secondary core(s) to initialize...",
281 expected_cores);
282 while (g_cores_ready.load(std::memory_order_acquire) < expected_cores) {
284 }
285 klog::Info("[RUNNER] All cores ready, starting SMP tests");
286
287 for (size_t i = 0; i < kTestCount; ++i) {
288 if (!test_cases[i].is_smp_test) {
289 continue;
290 }
291 auto& result = test_results[i];
292 result.status = TestThreadStatus::kRunning;
293
294 klog::Info("[SMP] Running: {}", test_cases[i].name);
295 bool smp_passed = test_cases[i].func();
296
297 result.exit_code = smp_passed ? 0 : 1;
298 result.status =
300
301 klog::Info("[SMP] Finished: {} — {}", test_cases[i].name,
302 smp_passed ? "PASS" : "FAIL");
303 }
304
305 auto runner = kstd::make_unique<TaskControlBlock>("test_runner", 10,
306 test_runner_entry, nullptr);
307 TaskManagerSingleton::instance().AddTask(std::move(runner));
308
309 TaskManagerSingleton::instance().Schedule();
310
311 __builtin_unreachable();
312}
auto WakeUpOtherCores() -> void
唤醒其余 core
Definition arch_main.cpp:68
auto ArchInit(int argc, const char **argv) -> void
体系结构相关初始化
Definition arch_main.cpp:48
auto ArchInitSMP(int argc, const char **argv) -> void
从核的体系结构相关初始化
Definition arch_main.cpp:65
auto DumpStack() -> void
打印调用栈
Definition backtrace.cpp:34
auto InterruptInit(int, const char **) -> void
体系结构相关中断初始化
auto InterruptInitSMP(int, const char **) -> void
从核的体系结构相关中断初始化
auto TimerInitSMP() -> void
从核的定时器初始化
Definition timer.cpp:35
auto TimerInit() -> void
初始化定时器
Definition timer.cpp:47
auto clone_system_test() -> bool
auto ctor_dtor_test() -> bool
auto DeviceInit() -> void
设备子系统初始化入口
Definition device.cpp:28
auto exit_system_test() -> bool
Exit 系统测试入口
auto fatfs_system_test() -> bool
auto FileSystemInit() -> void
文件系统子系统初始化入口
auto idle_scheduler_test() -> bool
auto interrupt_test() -> bool
auto MemoryInit() -> void
内存子系统初始化
Definition memory.cpp:71
auto MemoryInitSMP() -> void
多核内存子系统初始化
Definition memory.cpp:106
auto kernel_task_test() -> bool
auto CppInit() -> void
构造 c++ 全局对象
auto memory_test() -> bool
auto mutex_test() -> bool
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
void Pause()
Definition cpu_io.h:20
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
static __always_inline auto GetCurrentCore() -> PerCpu &
获取当前核心的 PerCpu 数据
Definition per_cpu.hpp:55
auto ramfs_system_test() -> bool
auto _start(int argc, const char **argv) -> void
负责 crtbegin 的工作
Definition main.cpp:134
每个 CPU 核心的局部数据
Definition per_cpu.hpp:23
auto sys_sleep(uint64_t ms) -> int
休眠指定毫秒数
Definition syscall.cpp:90
auto sys_exit(int code) -> int
退出当前进程或线程
Definition syscall.cpp:75
auto cfs_scheduler_test() -> bool
auto fifo_scheduler_test() -> bool
auto rr_scheduler_test() -> bool
auto spinlock_test() -> bool
void QemuExit(bool success)
测试结束后退出 QEMU,success=true 表示全部通过
auto wait_system_test() -> bool
Wait 系统测试入口
auto user_task_test() -> bool
auto thread_group_system_test() -> bool
线程组系统测试入口
auto virtual_memory_test() -> bool
TestThreadStatus
测试线程运行状态
@ kPassed
测试通过
@ kRunning
运行中
@ kTimeout
超时未完成
@ kPending
等待启动
@ kFailed
测试失败
size_t Pid
进程 ID 类型
void main()
Definition main.cpp:33