28 bool is_smp_test =
false;
31constexpr size_t kTestCount = 18;
33std::array<test_case, kTestCount> test_cases = {
53std::array<TestResult, kTestCount> test_results{};
55std::atomic<size_t> g_cores_ready{0};
57void test_thread_entry(
void* arg) {
58 auto idx =
reinterpret_cast<uint64_t
>(arg);
59 auto& test = test_cases[idx];
63 bool passed = test.func();
65 klog::Info(
"[TEST] Finished: {} — {}", test.name, passed ?
"PASS" :
"FAIL");
70void print_test_summary() {
75 klog::Info(
"========================================");
77 klog::Info(
"========================================");
79 for (
size_t i = 0; i < kTestCount; ++i) {
80 auto& r = test_results[i];
81 const char* tag =
"???";
105 if (test_cases[i].is_smp_test) {
106 klog::Info(
" [{}] {} (SMP, exit_code={})", tag, r.name, r.exit_code);
108 klog::Info(
" [{}] {} (pid={}, exit_code={})", tag, r.name, r.pid,
113 int total =
static_cast<int>(kTestCount);
115 klog::Info(
"========================================");
116 klog::Info(
" Total: {} | Passed: {} | Failed: {} | Timeout: {}", total,
117 passed, failed, timed_out);
118 klog::Info(
"========================================");
121void test_runner_entry(
void* ) {
122 auto& task_mgr = TaskManagerSingleton::instance();
123 auto* runner = task_mgr.GetCurrentTask();
126 int thread_test_count = 0;
128 for (
size_t i = 0; i < kTestCount; ++i) {
129 if (test_cases[i].is_smp_test) {
133 auto task = kstd::make_unique<TaskControlBlock>(
134 test_cases[i].name, 10, test_thread_entry,
reinterpret_cast<void*
>(i));
137 task->aux->parent_pid = runner->pid;
138 task->aux->pgid = runner->aux->pgid;
140 test_results[i].pid = task->pid;
143 task_mgr.AddTask(std::move(task));
147 klog::Info(
"[RUNNER] Spawned {} test threads, collecting via Wait()...",
152 constexpr int kMaxWaitRetries = 1200;
155 while (collected < thread_test_count && retries < kMaxWaitRetries) {
158 task_mgr.Wait(
static_cast<Pid>(-1), &status,
true,
false);
160 if (wait_result.has_value() && wait_result.value() > 0) {
161 Pid exited_pid = wait_result.value();
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;
169 klog::Info(
"[RUNNER] Collected: {} (pid={}, exit_code={}) — {}",
170 test_cases[i].name, exited_pid, status,
171 (status == 0) ?
"PASS" :
"FAIL");
183 for (
size_t i = 0; i < kTestCount; ++i) {
184 if (test_cases[i].is_smp_test) {
190 klog::Err(
"[RUNNER] Timeout: {} (pid={})", test_cases[i].name,
191 test_results[i].pid);
196 print_test_summary();
198 bool all_passed =
true;
199 for (
size_t i = 0; i < kTestCount; ++i) {
209void run_tests_smp() {
210 for (
const auto& test : test_cases) {
211 if (test.is_smp_test) {
217auto main_smp(
int argc,
const char** argv) ->
int {
222 TaskManagerSingleton::instance().InitCurrentCore();
226 g_cores_ready.fetch_add(1, std::memory_order_release);
230 TaskManagerSingleton::instance().Schedule();
232 __builtin_unreachable();
237auto _start(
int argc,
const char** argv) ->
void {
238 if (argv !=
nullptr) {
242 main_smp(argc, argv);
250auto main(
int argc,
const char** argv) ->
int {
251 per_cpu::PerCpuArraySingleton::create();
260 TaskManagerSingleton::create();
261 TaskManagerSingleton::instance().InitCurrentCore();
271 for (
size_t i = 0; i < kTestCount; ++i) {
272 test_results[i].name = test_cases[i].name;
274 test_results[i].exit_code = -1;
275 test_results[i].pid = 0;
279 size_t expected_cores = BasicInfoSingleton::instance().core_count - 1;
280 klog::Info(
"[RUNNER] Waiting for {} secondary core(s) to initialize...",
282 while (g_cores_ready.load(std::memory_order_acquire) < expected_cores) {
285 klog::Info(
"[RUNNER] All cores ready, starting SMP tests");
287 for (
size_t i = 0; i < kTestCount; ++i) {
288 if (!test_cases[i].is_smp_test) {
291 auto& result = test_results[i];
294 klog::Info(
"[SMP] Running: {}", test_cases[i].name);
295 bool smp_passed = test_cases[i].func();
297 result.exit_code = smp_passed ? 0 : 1;
301 klog::Info(
"[SMP] Finished: {} — {}", test_cases[i].name,
302 smp_passed ?
"PASS" :
"FAIL");
305 auto runner = kstd::make_unique<TaskControlBlock>(
"test_runner", 10,
306 test_runner_entry,
nullptr);
307 TaskManagerSingleton::instance().AddTask(std::move(runner));
309 TaskManagerSingleton::instance().Schedule();
311 __builtin_unreachable();
auto WakeUpOtherCores() -> void
唤醒其余 core
auto ArchInit(int argc, const char **argv) -> void
体系结构相关初始化
auto ArchInitSMP(int argc, const char **argv) -> void
从核的体系结构相关初始化
auto DumpStack() -> void
打印调用栈
auto InterruptInit(int, const char **) -> void
体系结构相关中断初始化
auto InterruptInitSMP(int, const char **) -> void
从核的体系结构相关中断初始化
auto TimerInitSMP() -> void
从核的定时器初始化
auto TimerInit() -> void
初始化定时器
auto clone_system_test() -> bool
auto ctor_dtor_test() -> bool
auto DeviceInit() -> void
设备子系统初始化入口
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
内存子系统初始化
auto MemoryInitSMP() -> void
多核内存子系统初始化
auto kernel_task_test() -> bool
auto CppInit() -> void
构造 c++ 全局对象
auto memory_test() -> bool
auto mutex_test() -> bool
auto GetCurrentCoreId() -> size_t
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 数据
auto ramfs_system_test() -> bool
auto _start(int argc, const char **argv) -> void
负责 crtbegin 的工作
auto sys_sleep(uint64_t ms) -> int
休眠指定毫秒数
auto sys_exit(int code) -> int
退出当前进程或线程
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