Skip to content

Commit 2826e7c

Browse files
MRNIUsisyphus-dev-aiclaude
authored
fix(ci): add safe.directory config for container submodule checkout (#198)
* fix: update unique_ptr Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: migrate Singleton<T> to etl::singleton<T> named aliases Replace custom Singleton<T> with etl::singleton<T> using per-type named aliases (e.g. BasicInfoSingleton, TaskManagerSingleton) defined centrally in kernel.h. Delete singleton.hpp. Update all call sites from Singleton<T>::GetInstance() to TypeSingleton::instance() and assignment-construction to TypeSingleton::create(). Update all documentation references. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(arch): move arch-specific singletons out of kernel.h and make interrupt controllers Interrupt members Move arch-specific singleton type aliases from shared kernel.h into per-arch directories, and convert interrupt controller singletons (PlicSingleton, ApicSingleton) into private members of each arch's Interrupt class, following the existing aarch64 pattern where Gic is already an Interrupt member. - Move Pl011Singleton to src/arch/aarch64/include/pl011_singleton.h - Move SerialSingleton to file-local scope in x86_64/early_console.cpp - Move Ns16550aSingleton to file-local scope in riscv64/interrupt_main.cpp - Add Plic plic_ member to riscv64 Interrupt with InitPlic() deferred init - Add Apic apic_ member to x86_64 Interrupt with InitApic() deferred init - Move APIC creation from ArchInit() to InterruptInit() (boot order fix) - Remove arch-specific #includes and #ifdefs from kernel.h Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(arch): remove static from Interrupt handler arrays Since Interrupt is used as etl::singleton (only one instance), static class members are semantically equivalent to non-static members. Remove static to eliminate the need for out-of-class definitions in .cpp files. - aarch64: interrupt_handlers -> interrupt_handlers_ (non-static member) - riscv64: interrupt_handlers_, exception_handlers_ (drop static + defs) - x86_64: interrupt_handlers_, idts_ (drop static + defs, keep alignas) The alignas(4096) on x86_64 members propagates correctly through etl::singleton via uninitialized_buffer_of<T> which uses alignas(etl::alignment_of<T>::value) on its storage. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: add cpu_io Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(arch): move arch-specific singletons from kernel.h to arch directories Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: string Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: string Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: klog Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: io_buffer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * doc: update AGENT.md Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * doc(etl): add ETL integration migration design plan Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(libc): wrap noexcept in __cplusplus guard for C compilation Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(task): add ETL message and router ID registry Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(task): replace CloneFlags enum and cpu_affinity with etl::flags Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(interrupt): replace InterruptFunc pointer with etl::delegate Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(task): replace TaskStatus enum with etl::fsm state machine Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(task): address code quality review findings for etl::fsm migration - C1: Add ReapTask(current) for orphan tasks in Exit() to prevent TCB leak - C2: Start FSM after default-constructing TCB in Clone() to avoid null deref - I2: Use STATE_ID constant in StateExited::on_event(MsgReap) - I3: Move GetStatus() implementation from header to .cpp file - I4: Enqueue idle task in kReady state, then transition to kRunning - M2: Restore dropped @todo SIGCHLD comment in exit.cpp - M5: Add [[nodiscard]] attribute to GetStatus() Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(kernel): add tick and panic observer interfaces using etl::observer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(kernel): add lifecycle and virtio message types for etl::message_router Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(plans): add ETL migration implementation plan Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: task_fsm Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: InterruptDelegate Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update include style Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: fsm Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: task_control_block Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * chore(docs): remove superseded etl-migration plan files Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(expected): add VirtIO/device error codes for device_framework unification Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add platform_config.hpp concrete impl for device_framework injection Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * build(device): use BEFORE in TARGET_INCLUDE_DIRECTORIES for platform_config override Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device_node): replace atomic<bool> with SpinLock-guarded bool, remove hand-rolled copy/move Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(df_bridge): remove DeviceStorage and ToKernelError, error types now unified Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(driver_registry): add etl::flat_map index for O(log N) platform driver lookup Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(virtio_blk_driver): remove Traits template param, use unified error and Storage types Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): remove PlatformTraits template usage, unify error handling Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(arch/riscv64): remove PlatformTraits template param from VirtioBlkDriver usage Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(device): add kMaxSpinIterations to PlatformTraits; use TryBind() in DeviceManager::ProbeAll() Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * chore(submodule): bump device_framework to merged main (440bfe7) device_framework feature/device-refactor merged into main: - Traits template elimination via platform_config.hpp injection - Unified error handling (PlatformErrorCode) - Storage<T> freestanding optional added - All tests updated for non-template API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): delete placeholder and redundant header files Inline PlatformTraits struct into platform_config.hpp and delete the now-redundant platform_traits.hpp. Also delete zero-caller stubs: acpi_bus.hpp, pci_bus.hpp, virtio_messages.hpp. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): simplify device module — remove Driver concept and variant types Replace template Register<D>() + Driver concept with plain DriverEntry function-pointer struct. Flatten DeviceNode to pure data (remove variant BusId, DeviceResource, DMA buffer, SpinLock). Move DMA allocation into VirtioBlkDriver::Probe(). Delete df_bridge.hpp; introduce mmio_helper.hpp. Net: ~1149 -> ~570 lines (~50% reduction), 13 -> 8 headers. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(arch/riscv64,device): update interrupt_main and virtio_blk_driver for new driver API - Replace DriverRegistry::GetDriverInstance<VirtioBlkDriver>() with VirtioBlkDriver::Instance() in interrupt_main.cpp (lines 100, 209) - Remove unused #include "driver_registry.hpp" from interrupt_main.cpp - Add missing #include "io_buffer.hpp" to virtio_blk_driver.hpp - Fix kstd::unique_ptr<IoBuffer> -> etl::unique_ptr<IoBuffer> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(device): add device_framework integration design doc Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * chore(device): create driver/ subdirectory skeleton Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add traits.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add ops/device_ops_base.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add ops/char_device.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add ops/block_device_ops.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/mmio_accessor.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/storage.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/uart_device.hpp inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/ns16550a/ inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/pl011/ inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/virtio/defs.h + traits.hpp (task 11) Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/virtio/transport/ (task 12) Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/virtio/virt_queue/ inlined from device_framework (task 13) Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/virtio/device/ inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add detail/acpi/ inlined from device_framework Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add pl011/acpi facade headers and update driver includes to inline headers Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(arch): replace device_framework includes with inlined driver headers Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * build: remove device_framework from CMake and .gitmodules Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * chore(device): remove device_framework submodule and platform_config.hpp hack Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(device): add platform_config.hpp for inlined VirtIO driver and fix unit-test CMake link Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: apply clang-format to VirtIO device and transport headers Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: remove plan Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): replace raw array+ptr with etl::vector/flat_map in DriverRegistry Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): migrate Ns16550aDriver to etl::delegate, remove DriverDescriptor Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): migrate VirtioBlkDriver to etl::optional + etl::delegate Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): delete detail/storage.hpp, superseded by etl::optional Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(device): update AGENTS.md for ETL refactor Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(device): fix duplicate section in AGENTS.md Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: add device module refactor design document Add design doc for src/device/ refactoring: - Delete ~1000 lines of dead ops/ CRTP layer - Replace VirtioBlkDriver with unified virtio::Probe() interface - Runtime transport/device-type detection via std::variant - Preserve detail/virtio/ structure for multi-device extensibility Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): extract VirtioBlkVfsAdapter to dedicated header Move VirtioBlkBlockDevice class (renamed VirtioBlkVfsAdapter) out of device.cpp into its own header. No functional change. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test(device): add failing tests for VirtioDriver Tests expect VirtioDriver::GetEntry() and MatchStatic() which will be implemented in the next task (TDD). Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add unified VirtioDriver with runtime device-type dispatch Replace VirtioBlkDriver with VirtioDriver that auto-detects VirtIO device type (blk/net/gpu/...) at runtime by reading device_id register. Caller (DeviceInit) no longer needs to know about VirtIO device types. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * build(device): add virtio_driver.cpp to device library sources Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): update DeviceInit to use unified VirtioDriver Replace VirtioBlkDriver::GetEntry() with VirtioDriver::GetEntry(). DeviceInit no longer mentions specific VirtIO device types. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): ns16550a_driver include ns16550a.hpp directly Remove dependency on ns16550a_device.hpp (CRTP wrapper, to be deleted). Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): pl011_driver include pl011.hpp directly Remove dependency on pl011_device.hpp (CRTP wrapper, to be deleted). Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): delete dead ops/ CRTP layer and unused device wrappers Remove ~1000 lines of dead code: - driver/ops/ (device_ops_base.hpp, char_device.hpp, block_device_ops.hpp) - driver/detail/uart_device.hpp - driver/detail/ns16550a/ns16550a_device.hpp - driver/detail/pl011/pl011_device.hpp - driver/detail/virtio/device/virtio_blk_device.hpp - driver/virtio_blk_driver.hpp (replaced by virtio_driver.hpp) Also add GetIrq()/HandleInterrupt() to VirtioDriver and update riscv64/interrupt_main.cpp to use VirtioDriver + Ns16550a directly. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(device): update AGENTS.md for new VirtioDriver architecture - Document virtio_driver.cpp as the second .cpp exception - Add VirtIO device extension guide (add device_id case only) - Remove references to deleted ops/ layer and virtio_blk_driver Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): restructure drivers into per-driver subdirectories - Each driver (ns16550a, pl011, acpi, virtio) now lives in its own subdirectory with an independent ADD_LIBRARY(xxx_driver INTERFACE) CMake target - Delete detail/ directory; headers moved directly into driver subdirectories (ns16550a/, pl011/, acpi/, virtio/) - device target changed from INTERFACE to STATIC with PRIVATE driver dependencies; consumers access hardware only through DeviceManager - device CMakeLists: use explicit compile-only deps instead of kernel_link_libraries to avoid leaking -nostdlib/-T link.ld into unit-test link command - Fix aarch64: add Pl011Device alias, HandleInterrupt stub, remove stale Open() call in early_console.cpp - Fix virtio traits.hpp: change self-referential include to ../traits.hpp - Arch code links driver targets explicitly as a documented exception - All three arch builds and 163 unit tests pass Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device,fdt): add ForEachDeviceNode filter and split device_manager - kernel_fdt.hpp: add ForEachDeviceNode() inline template that skips infrastructure nodes (interrupt-controller, #clock-cells, cpu, memory device_type) to suppress spurious 'no driver' log noise - device_manager.hpp: extract ProbeAll/FindDevice/FindDevicesByType to device_manager.cpp; keep RegisterBus<B> template in header - device_manager.cpp: implement the three methods with assert-based precondition checks and ProbeAll no_driver_count summary log - virtio: fix missing newlines in klog::Debug format strings - doc/plans: add design doc and implementation plan Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): assert-harden mmio_helper and use ForEachDeviceNode - driver_registry.hpp: replace mmio_base==0 error return in mmio_helper::Prepare with assert() — bad node is a driver bug, not a recoverable runtime condition; add #include <cassert> - platform_bus.hpp: switch Enumerate to fdt_.ForEachDeviceNode so infrastructure nodes (interrupt-controller, clock, cpu, memory) are skipped before driver matching, eliminating 'no driver' noise Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(virtio): reorganize device/ into per-type subdirectories Move virtio_blk.hpp, virtio_blk_defs.h, virtio_blk_vfs_adapter.hpp into device/blk/, and placeholder headers into console/, net/, gpu/, input/. Update all include paths and header guards accordingly. device_initializer.hpp stays at device/ root as it is cross-device. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(virtio): modernize VirtioBlk with std::array Replace raw C arrays slots_[kMaxInflight] with std::array<RequestSlot, kMaxInflight> and local IoVec[] with std::array<IoVec, kMaxSgElements> in DoEnqueue(). Replace static kNames[] with constexpr std::array<const char*, 4> in GetName(). Also zero-initialize slot_bitmap_ explicitly with {}. Note: std::bitset was evaluated but omitted — std::bitset<N>::to_ulong() references exception machinery (__throw_out_of_range_fmt) in GCC 14's libstdc++, which is incompatible with this freestanding kernel build. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: update cpu_io Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: mmio_accessor Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(arch/riscv64): add etl_putchar shim for ETL print support Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(arch/aarch64): add etl_putchar shim for ETL print support Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(arch/x86_64): add etl_putchar shim for ETL print support Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): migrate klog calls to ETL format syntax Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(task): migrate klog calls to ETL format syntax Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(arch): migrate klog calls to ETL format syntax Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(src): migrate klog calls to ETL format syntax Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(klog): rewrite kernel_log.hpp with type-safe {} format syntax - Replace printf-style %s/%d format strings with {}-based syntax - Add KernelFmtStr<Args...> + KernelFormatString alias with type_identity_t for correct CTAD (mirrors std::format_string pattern) - Add FormatArg() overloads for freestanding-safe single-arg printing - Add LogFormat() recursive walker for format string processing - Keep stream-style API (klog::info <<) unchanged - Add ETL_FORCE_STD_INITIALIZER_LIST to prevent ETL/stdlib collision when ETL_NO_STL is set in freestanding mode - Migrate clone.cpp and syscall.cpp to {} syntax - Verified clean build on riscv64, aarch64, x86_64 Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(libc): remove nanoprintf, replace sk_printf with emit helpers - Delete sk_printf/sk_snprintf/sk_vsnprintf API from sk_stdio.h and sk_stdio.c - Add four __always_inline emit helpers: sk_emit_str, sk_emit_sint, sk_emit_uint, sk_emit_hex - Migrate kernel_log.hpp, spinlock.hpp, kstd_iostream.cpp, kstd_libcxx.cpp, schedule.cpp, syscall.cpp to emit helpers - Replace BmallocLogger with empty no-op implementation - Remove nanoprintf git submodule and CMake integration - cmake-lint skipped: pre-existing cmakelang internal crash (upstream bug) Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: update cpu_io Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(libc): replace sk_putchar with etl_putchar Remove the sk_putchar function pointer (and its unused ctx parameter). etl_putchar(int c) — already defined per-arch in early_console.cpp — becomes the sole low-level output primitive. - Delete sk_stdio.c (contained only dummy_putchar + sk_putchar) - Remove sk_stdio.c from libc CMakeLists - sk_stdio.h declares etl_putchar; sk_emit_* helpers call it directly - riscv64/early_console: drop EarlyConsole struct (SBI always ready) - aarch64/x86_64 early_console: collapse console_putchar into etl_putchar - Replace all sk_putchar(c, nullptr) -> etl_putchar(c) across 8 files Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(klog): simplify kernel_log — 8 complexity fixes - Support {:x}/{:#x}/{:X}/{:#X} format specifiers for integers - Unify type printing: operator<< delegates to FormatArg - Extract EmitHeader<Level>() to eliminate duplicated prefix code - Remove redundant if constexpr level checks in struct constructors - Replace throw with non-constexpr call in consteval context (freestanding safe) - Fix DebugBlob: use if constexpr only, remove #ifdef SIMPLEKERNEL_DEBUG - Rename LogStarter -> LogStream for clarity - Add auto-newline in LogEmit/~LogLine, strip trailing backslash n from all call sites (63 files: src/**/*.cpp, src/**/*.hpp, tests/**/*.cpp) Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: replace nanoprintf with etl Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: remove plans Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: remove kstd::ostream Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: sk_print_str Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: replace __attribute__ with [[xxx]] Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: replace __attribute__ with [[xxx]] Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: backtrace Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: virtio Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): unify driver singletons to etl::singleton Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: remove etl docs Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(device): resolve singleton alias forward-reference in GetEntry() Replace XxxSingleton::instance() with etl::singleton<Xxx>::instance() inside GetEntry() where the type alias is not yet declared. Affects Pl011Driver, Ns16550aDriver, and VirtioDriver. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(device): add DmaRegion type and IoBuffer::ToDmaRegion() Introduce DmaRegion{virt, phys, size} value type, VirtToPhysFunc callback, and IdentityVirtToPhys default in io_buffer.hpp. Add ToDmaRegion() to IoBuffer for converting buffers to DMA-ready regions. Includes 8 GoogleTest unit tests and implementation plan. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(device): replace void* DMA with DmaRegion + VirtToPhys abstraction Refactor SplitVirtqueue, VirtioBlk, and VirtioDriver to use DmaRegion instead of raw void*/uintptr_t pairs. VirtioBlk::Create() now accepts separate vq_dma and slot_dma regions with a VirtToPhysFunc callback, eliminating hardcoded identity-mapping assumptions. RequestSlot memory is allocated from a dedicated DMA buffer for device-accessible physical addresses. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: sk_print_str Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: device Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(log): add per-CPU lock-free LogLineRaw/LogStreamRaw interfaces Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(arch): use lock-free klog::raw_err in DumpStack to prevent deadlock Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: klog Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: klog Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor: klog Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: add stb and EasyLogger Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: add stb and EasyLogger Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: add stb and EasyLogger Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: add stb and EasyLogger Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(log): add MPMC log refactor design and implementation plan Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): rewrite kernel_log.hpp with MPMC lock-free queue Replace SpinLock-based stream logging with Vyukov lock-free MPMC queue. New API: klog::Info/Warn/Err/Debug (printf-style), klog::Flush, klog::RawPut. Remove: LogLine, LogLineRaw, LogStream, LogStreamRaw, DebugBlob, klog::hex/HEX. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/main.cpp to new klog API Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/arch/x86_64/ to new klog API Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/arch/riscv64/ to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/arch/aarch64/ to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/memory/ to new klog API Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/device/ to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/task/ to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate src/filesystem/ to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): migrate remaining headers and syscall to new klog API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * refactor(log): update commented-out klog calls in spinlock.hpp to new API Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(log): replace __always_inline with inline on variadic klog functions GCC cannot inline functions using variable argument lists (...). Change Debug(), Info(), Warn(), Err() from __always_inline to inline. Flush() and RawPut() remain __always_inline as they are non-variadic. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(log): add missing cpu_io.h include for GetCurrentCoreId kernel_log.hpp uses cpu_io::GetCurrentCoreId() but did not include the header, causing 'cpu_io has not been declared' build errors. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: mpsc log Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: etl format Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: etl format Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: log with core id Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: log with core id Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: working on smp Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: update etl Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * 3rd: update etl Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: add boot_task Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: move TimerInit to main Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: move TimerInit to main Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * doc: update AGENTS.md Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: use pragma once Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style(arch,filesystem,memory): update headers to coding standards - Add trailing return types, [[nodiscard]], @brief, brace init, constructor groups - Arch: interrupt.h (riscv64/aarch64/x86_64), plic.h, gic.h, apic.h, io_apic.h, local_apic.h, sipi.h - Filesystem: file_descriptor.hpp, vfs.hpp, vfs_types.hpp, mount.hpp, vfs_internal.hpp, ramfs.hpp, fatfs.hpp - Memory: virtual_memory.hpp - Build verified on riscv64 and x86_64 Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: use trailing return types in .cpp and arch.h Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: update AGENTS.md Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * style: update Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs: update AGENTS.md Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: warnning Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(multi): address Copilot review findings across IO APIC, VFS, device, and DMA - io_apic: add early return after OOB IRQ check in SetIrqRedirection/MaskIrq/UnmaskIrq - mkdir: add NUL-termination after strncpy on dentry name - lookup: replace broken mount-point loop with FindByMountDentry - file_descriptor: fix open_count_ over-counting in SetupStandardFiles - io_buffer: fix size_t overflow in SubRegion bounds check - open/mkdir: reject path components exceeding buffer sizes - file_descriptor: use address-based lock ordering in move-assignment - virtio_driver: pass slot_align to IoBuffer for consistency - diskio: add nullptr guard for buff in disk_ioctl Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update devcontainer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update devcontainer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update devcontainer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update devcontainer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: working on signal Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: update st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update ci Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: update ci Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(cmake): create /srv/tftp directory before symlinking Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(devcontainer): create /srv/tftp for QEMU built-in TFTP server Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(devcontainer): add libssl-dev for U-Boot build U-Boot's image.h requires openssl/evp.h for FIT image signing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(devcontainer): add aarch64-linux-gnu-cpp alternative for OP-TEE build OP-TEE's build system requires aarch64-linux-gnu-cpp which was not symlinked via update-alternatives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(syscall): wire signal and affinity syscalls into dispatcher Add kSyscallSchedGetaffinity and kSyscallSchedSetaffinity constants for all architectures. Add dispatcher cases for sys_kill, sys_sigaction, sys_sigprocmask, sys_sched_getaffinity, and sys_sched_setaffinity. Implement sys_kill, sys_sigaction, and sys_sigprocmask function bodies that delegate to TaskManager signal methods. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test(task): add yield system test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: claen main.cpp Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test(task): add fork system test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test(task): add signal, affinity, tick, zombie_reap, stress system tests - signal_test: SIGTERM/SIGKILL default, SIG_IGN, sigprocmask, error paths - affinity_test: get/set affinity syscalls, cross-task, error paths - tick_test: tick increment, sleep timing, runtime tracking - zombie_reap_test: zombie reaping, orphan reparenting, multi-child Wait - stress_test: 20 concurrent tasks, wait non-child, rapid create-exit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: fix st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test: working on st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: st Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: timer seq bug Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix: timer seq bug Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: remove x86_64 Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(ci): use virtio-net-device and correct codecov path for ARM runner Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * perf(ci): parallelize jobs, prebuilt Docker image, caching and shallow clone - Split single serial job into parallel build-riscv64 + build-aarch64 jobs - Add dev-image.yml workflow to build/push dev container to GHCR - Replace devcontainers/ci per-step with container: for shared container - Use shallow clone (fetch-depth: 1) and shallow submodules (--depth 1) - Add CMake build cache via actions/cache - Reduce system test runs to 3 for PRs (10 for push/release) - Add concurrency group to cancel superseded runs - Upgrade codecov-action v3->v4, actions-gh-pages v3->v4 Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * test(task): add balance work-stealing unit tests Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * chore(misc): remove outdated TODO/FIXME comments Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(task): implement Balance() work-stealing load balancer Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat(task): integrate Balance() into TickUpdate() on 64-tick interval Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * docs(task): update AGENTS.md to reflect Balance() implementation Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * feat: balance Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(ci): add safe.directory config for container submodule checkout When running inside a container job, git submodule update fails with exit code 128 due to directory ownership mismatch (container runs as root, workspace owned by runner user). Adding safe.directory wildcard before submodule init resolves this. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> * fix(ci): detect riscv64 system test failures by checking output The riscv64 system test step only checked the cmake exit code, which is always 0 even when individual tests fail inside QEMU. Align with the aarch64 approach: capture output to file, grep for "Failed: 0" to determine pass/fail. Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> --------- Signed-off-by: Niu Zhihong <zhihong@nzhnb.com> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f24ac7e commit 2826e7c

13 files changed

Lines changed: 509 additions & 18 deletions

File tree

.github/workflows/workflow.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ jobs:
3232
fetch-depth: 1
3333

3434
- name: Shallow submodule init
35-
run: git submodule update --init --recursive --depth 1
35+
run: |
36+
git config --global --add safe.directory '*'
37+
git submodule update --init --recursive --depth 1
3638
3739
- name: Cache CMake build (riscv64)
3840
uses: actions/cache@v4
@@ -51,7 +53,9 @@ jobs:
5153
run: |
5254
for i in $(seq 1 $SYSTEM_TEST_RUNS); do
5355
echo "=== riscv64 System Test Run $i/$SYSTEM_TEST_RUNS ==="
54-
if ! timeout 300 cmake --build build_riscv64 --target system_test_run; then
56+
timeout 300 cmake --build build_riscv64 --target system_test_run > /tmp/st_out_$i.txt 2>&1 || true
57+
cat /tmp/st_out_$i.txt
58+
if ! grep -q "Failed: 0" /tmp/st_out_$i.txt; then
5559
echo "riscv64 system test run $i/$SYSTEM_TEST_RUNS FAILED"
5660
exit 1
5761
fi
@@ -80,7 +84,9 @@ jobs:
8084
fetch-depth: 1
8185

8286
- name: Shallow submodule init
83-
run: git submodule update --init --recursive --depth 1
87+
run: |
88+
git config --global --add safe.directory '*'
89+
git submodule update --init --recursive --depth 1
8490
8591
- name: Cache CMake build (aarch64)
8692
uses: actions/cache@v4

src/arch/aarch64/link.ld

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,9 @@ SECTIONS
168168
*(.dynbss)
169169
*(.bss .bss.* .gnu.linkonce.b.*)
170170
*(COMMON)
171-
/* Align here to ensure that the .bss section occupies space up to
172-
_end. Align after .bss to ensure correct alignment even if the
173-
.bss section disappears because there are no input sections.
174-
FIXME: Why do we need it? When there is no .bss section, we do not
175-
pad the .data section. */
171+
/* Align here to ensure that the .bss section occupies space up to
172+
_end. Align after .bss to ensure correct alignment even if the
173+
.bss section disappears because there are no input sections. */
176174
. = ALIGN(. != 0 ? 64 / 8 : 1);
177175
}
178176
_bss_end__ = .; __bss_end__ = .;

src/arch/riscv64/link.ld

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,8 @@ SECTIONS {
178178
*(.bss .bss.* .gnu.linkonce.b.*)
179179
*(COMMON)
180180
/* Align here to ensure that the .bss section occupies space up to
181-
_end. Align after .bss to ensure correct alignment even if the
182-
.bss section disappears because there are no input sections.
183-
FIXME: Why do we need it? When there is no .bss section, we do not
184-
pad the .data section. */
181+
_end. Align after .bss to ensure correct alignment even if the
182+
.bss section disappears because there are no input sections. */
185183
. = ALIGN(. != 0 ? 64 / 8 : 1);
186184
}
187185
. = ALIGN(64 / 8);

src/task/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ mutex.cpp # Mutex implementation (uses SpinLock internally)
4141
- Schedulers own their internal run queues — TaskManager dispatches to per-policy schedulers
4242
- `TaskManagerSingleton::instance()` (defined in `task_manager.hpp`) is the global entry point
4343
- TCB contains arch-specific context pointer — populated by `switch.S`
44-
- TODO in `task_manager.cpp`: task stealing across cores (not yet implemented)
44+
- `Balance()` in `task_manager.cpp`: cross-core work-stealing (steals kNormal tasks from most-loaded core, called every 64 ticks)
4545

4646
## ANTI-PATTERNS
4747
- **DO NOT** call Schedule() before TaskManager initialization in boot sequence

src/task/task_manager.cpp

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,82 @@ auto TaskManager::FindTask(Pid pid) -> TaskControlBlock* {
179179
}
180180

181181
auto TaskManager::Balance() -> void {
182-
// 算法留空
183-
// TODO: 检查其他核心的运行队列长度,如果比当前核心长,则窃取任务
182+
auto current_core = cpu_io::GetCurrentCoreId();
183+
auto& current_sched = cpu_schedulers_[current_core];
184+
185+
// 获取当前核心 kNormal 队列长度(无锁快速检查)
186+
size_t current_load = 0;
187+
if (current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]) {
188+
current_load =
189+
current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]
190+
->GetQueueSize();
191+
}
192+
193+
// 寻找负载最高的核心
194+
size_t max_load = 0;
195+
size_t max_core = current_core;
196+
197+
for (size_t core_id = 0; core_id < SIMPLEKERNEL_MAX_CORE_COUNT; ++core_id) {
198+
if (core_id == current_core) {
199+
continue;
200+
}
201+
auto& other_sched = cpu_schedulers_[core_id];
202+
if (other_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]) {
203+
size_t load =
204+
other_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]
205+
->GetQueueSize();
206+
if (load > max_load) {
207+
max_load = load;
208+
max_core = core_id;
209+
}
210+
}
211+
}
212+
213+
// 仅当差值 > 1 时才窃取(避免 ping-pong)
214+
if (max_core == current_core || max_load <= current_load + 1) {
215+
return;
216+
}
217+
218+
// 按核心 ID 顺序获取锁,防止死锁
219+
auto& source_sched = cpu_schedulers_[max_core];
220+
size_t first_core = (current_core < max_core) ? current_core : max_core;
221+
size_t second_core = (current_core < max_core) ? max_core : current_core;
222+
223+
LockGuard<SpinLock> lock_first(cpu_schedulers_[first_core].lock);
224+
LockGuard<SpinLock> lock_second(cpu_schedulers_[second_core].lock);
225+
226+
// 重新检查(持锁后条件可能已变化)
227+
auto* source_scheduler =
228+
source_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)].get();
229+
auto* dest_scheduler =
230+
current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]
231+
.get();
232+
233+
if (!source_scheduler || !dest_scheduler) {
234+
return;
235+
}
236+
237+
size_t source_load = source_scheduler->GetQueueSize();
238+
size_t dest_load = dest_scheduler->GetQueueSize();
239+
240+
if (source_load <= dest_load + 1) {
241+
return;
242+
}
243+
244+
auto* stolen = source_scheduler->PickNext();
245+
if (!stolen) {
246+
return;
247+
}
248+
249+
if (stolen->aux && stolen->aux->cpu_affinity.value() != UINT64_MAX &&
250+
!(stolen->aux->cpu_affinity.value() & (1UL << current_core))) {
251+
source_scheduler->Enqueue(stolen);
252+
return;
253+
}
254+
255+
dest_scheduler->Enqueue(stolen);
256+
klog::Debug("Balance: Stole task '{}' (pid={}) from core {} to core {}",
257+
stolen->name, stolen->pid, max_core, current_core);
184258
}
185259

186260
auto TaskManager::ReapTask(TaskControlBlock* task) -> void {

src/task/tick_update.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ auto TaskManager::TickUpdate() -> void {
6767
}
6868
}
6969

70+
if (cpu_sched.scheduler_started && (cpu_sched.local_tick % 64) == 0) {
71+
Balance();
72+
}
73+
7074
if (need_preempt && cpu_sched.scheduler_started) {
7175
Schedule();
7276
}

tests/integration_test/aarch64_minimal/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @copyright Copyright The SimpleKernel Contributors
3-
* @brief TODO: Add description
3+
* @brief AArch64 minimal boot test
44
*/
55

66
#include <cstdarg>

tests/system_test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ ADD_EXECUTABLE (
3434
tick_test.cpp
3535
zombie_reap_test.cpp
3636
stress_test.cpp
37+
balance_test.cpp
3738
${CMAKE_SOURCE_DIR}/src/syscall.cpp
3839
${CMAKE_SOURCE_DIR}/src/io_buffer.cpp)
3940

0 commit comments

Comments
 (0)