From ab38d60eb0e74d2535cc6dcd51d1403d46d20b10 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 00:59:15 +0800 Subject: [PATCH 1/7] squash 28dc592 to 4f805fb --- Cargo.lock | 148 +++++++++++++++++++++++----- Makefile | 5 +- api/arceos_api/src/imp/mod.rs | 7 +- api/arceos_api/src/lib.rs | 3 + api/arceos_posix_api/src/imp/sys.rs | 2 +- configs/custom/x86_64-pc-oslab.toml | 5 +- configs/dummy.toml | 5 +- modules/axhal/Cargo.toml | 10 +- modules/axhal/build.rs | 2 +- modules/axhal/src/dummy.rs | 4 + modules/axhal/src/lib.rs | 58 +++++++++++ modules/axipi/src/lib.rs | 2 +- modules/axruntime/Cargo.toml | 2 +- modules/axruntime/src/lib.rs | 7 +- modules/axruntime/src/mp.rs | 11 ++- modules/axtask/Cargo.toml | 1 - modules/axtask/src/api.rs | 27 ++++- modules/axtask/src/run_queue.rs | 9 +- modules/axtask/src/task.rs | 4 +- scripts/make/config.mk | 7 +- ulib/axstd/src/thread/mod.rs | 2 +- 21 files changed, 265 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8539206aef..203d24e78b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,11 +119,11 @@ version = "0.1.0" dependencies = [ "axplat-aarch64-bsta1000b", "axplat-aarch64-phytium-pi", - "axplat-aarch64-qemu-virt", + "axplat-aarch64-qemu-virt 0.2.0", "axplat-aarch64-raspi", - "axplat-loongarch64-qemu-virt", - "axplat-riscv64-qemu-virt", - "axplat-x86-pc", + "axplat-loongarch64-qemu-virt 0.2.0", + "axplat-riscv64-qemu-virt 0.2.0", + "axplat-x86-pc 0.2.0", "axstd", "cfg-if", ] @@ -502,11 +502,11 @@ dependencies = [ "axconfig", "axcpu", "axlog", - "axplat", - "axplat-aarch64-qemu-virt", - "axplat-loongarch64-qemu-virt", - "axplat-riscv64-qemu-virt", - "axplat-x86-pc", + "axplat 0.3.0", + "axplat-aarch64-qemu-virt 0.3.0", + "axplat-loongarch64-qemu-virt 0.3.0", + "axplat-riscv64-qemu-virt 0.3.0", + "axplat-x86-pc 0.3.0", "cfg-if", "heapless 0.8.0", "kernel_guard", @@ -619,6 +619,21 @@ dependencies = [ "memory_addr", ] +[[package]] +name = "axplat" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397e19d768dbf9573cf40663d65671a98c8b8a2a3b3947191d4aab6a33e01a15" +dependencies = [ + "axplat-macros", + "bitflags 2.9.2", + "const-str", + "crate_interface", + "handler_table", + "kspin", + "memory_addr", +] + [[package]] name = "axplat-aarch64-bsta1000b" version = "0.2.0" @@ -627,8 +642,8 @@ checksum = "af884a8e67b199c395d634e0a2fa9cd954279dd9abe9e672b84e833506f8466c" dependencies = [ "axconfig-macros", "axcpu", - "axplat", - "axplat-aarch64-peripherals", + "axplat 0.2.0", + "axplat-aarch64-peripherals 0.2.0", "dw_apb_uart", "kspin", "log", @@ -646,7 +661,27 @@ dependencies = [ "arm_pl011", "arm_pl031", "axcpu", - "axplat", + "axplat 0.2.0", + "int_ratio", + "kspin", + "lazyinit", + "log", + "page_table_entry", + "spin 0.10.0", +] + +[[package]] +name = "axplat-aarch64-peripherals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d65e6a09f3d1f0af076efa21eb1325d675431e0b313e25df256ddf2344bf6f" +dependencies = [ + "aarch64-cpu 10.0.0", + "arm-gic-driver", + "arm_pl011", + "arm_pl031", + "axcpu", + "axplat 0.3.0", "int_ratio", "kspin", "lazyinit", @@ -663,8 +698,8 @@ checksum = "d4c893f78d02cfa594bbe7f5880e69c610f79c119a28a4c2d095dfca95287f0e" dependencies = [ "axconfig-macros", "axcpu", - "axplat", - "axplat-aarch64-peripherals", + "axplat 0.2.0", + "axplat-aarch64-peripherals 0.2.0", "log", "page_table_entry", ] @@ -677,8 +712,22 @@ checksum = "6f03bfe81ebc5b2f567eecadcab221107b90f394485dd0da39334411a676d81a" dependencies = [ "axconfig-macros", "axcpu", - "axplat", - "axplat-aarch64-peripherals", + "axplat 0.2.0", + "axplat-aarch64-peripherals 0.2.0", + "log", + "page_table_entry", +] + +[[package]] +name = "axplat-aarch64-qemu-virt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a67e4110907e19c3ab1353e4386f4656aab395c83656cfee22ba6b49ed35250" +dependencies = [ + "axconfig-macros", + "axcpu", + "axplat 0.3.0", + "axplat-aarch64-peripherals 0.3.0", "log", "page_table_entry", ] @@ -692,8 +741,8 @@ dependencies = [ "aarch64-cpu 10.0.0", "axconfig-macros", "axcpu", - "axplat", - "axplat-aarch64-peripherals", + "axplat 0.2.0", + "axplat-aarch64-peripherals 0.2.0", "log", "page_table_entry", ] @@ -706,7 +755,24 @@ checksum = "8c404064c74824b2c509e1d84f2ae0cbd9240a3274fb4053dc81b9ad120b5962" dependencies = [ "axconfig-macros", "axcpu", - "axplat", + "axplat 0.2.0", + "kspin", + "lazyinit", + "log", + "loongArch64", + "ns16550a", + "page_table_entry", +] + +[[package]] +name = "axplat-loongarch64-qemu-virt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00a0c4b0a25488e6a9b536a55fae2153d14ef40bd931b2c28bf387a95ad3fb80" +dependencies = [ + "axconfig-macros", + "axcpu", + "axplat 0.3.0", "chrono", "kspin", "lazyinit", @@ -735,7 +801,21 @@ checksum = "b8d95d76dfa65d75d07380ac13692c3b0c5bd6ae5b68df7bbede1f2e7181027a" dependencies = [ "axconfig-macros", "axcpu", - "axplat", + "axplat 0.2.0", + "log", + "riscv", + "sbi-rt", +] + +[[package]] +name = "axplat-riscv64-qemu-virt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb75b0b52fd2289ec461a3ea3aba978cb943fb07fb023d5edc2c8efe079eb724" +dependencies = [ + "axconfig-macros", + "axcpu", + "axplat 0.3.0", "log", "riscv", "riscv_goldfish", @@ -750,7 +830,31 @@ checksum = "4aef32b01b5b7e87e9f69933b64b704bc5d731adda2cdd24fc0a29cf0c359211" dependencies = [ "axconfig-macros", "axcpu", - "axplat", + "axplat 0.2.0", + "bitflags 2.9.2", + "heapless 0.9.1", + "int_ratio", + "kspin", + "lazyinit", + "log", + "multiboot", + "percpu", + "raw-cpuid 11.5.0", + "uart_16550", + "x2apic", + "x86", + "x86_64", +] + +[[package]] +name = "axplat-x86-pc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3488a8857c3e66da47a320e4c6ebba10f6218481e31ca3f2e00f927e1ad68c1" +dependencies = [ + "axconfig-macros", + "axcpu", + "axplat 0.3.0", "bitflags 2.9.2", "heapless 0.9.1", "int_ratio", @@ -781,7 +885,7 @@ dependencies = [ "axlog", "axmm", "axnet", - "axplat", + "axplat 0.3.0", "axtask", "chrono", "crate_interface", diff --git a/Makefile b/Makefile index 517fc0ef37..c1a2853a0f 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,10 @@ # - `ARCH`: Target architecture: x86_64, riscv64, aarch64, loongarch64 # - `MYPLAT`: Package name of the target platform crate. # - `PLAT_CONFIG`: Path to the platform configuration file. -# - `SMP`: Number of CPUs. If not set, use the default value from platform config. +# - `SMP`: Override maximum CPU number specified in the platform config. For +# statically configured platforms, this is also the number of CPUs to boot +# and for platforms with runtime CPU detection, this is the upper limit of +# CPUs. # - `MODE`: Build mode: release, debug # - `LOG:` Logging level: warn, error, info, debug, trace # - `V`: Verbose level: (empty), 1, 2 diff --git a/api/arceos_api/src/imp/mod.rs b/api/arceos_api/src/imp/mod.rs index a8dbdfdb74..4c80b995a7 100644 --- a/api/arceos_api/src/imp/mod.rs +++ b/api/arceos_api/src/imp/mod.rs @@ -39,6 +39,11 @@ mod stdio { } } +mod sys { + pub use axhal::cpu_num as ax_get_cpu_num; + pub use axhal::power::system_off as ax_terminate; +} + mod time { pub use axhal::time::{ TimeValue as AxTimeValue, monotonic_time as ax_monotonic_time, wall_time as ax_wall_time, @@ -47,8 +52,8 @@ mod time { pub use self::mem::*; pub use self::stdio::*; +pub use self::sys::*; pub use self::task::*; pub use self::time::*; -pub use axhal::power::system_off as ax_terminate; pub use axio::PollState as AxPollState; diff --git a/api/arceos_api/src/lib.rs b/api/arceos_api/src/lib.rs index 95658a17e6..d91da0c342 100644 --- a/api/arceos_api/src/lib.rs +++ b/api/arceos_api/src/lib.rs @@ -32,6 +32,9 @@ pub mod sys { define_api! { /// Shutdown the whole system and all CPUs. pub fn ax_terminate() -> !; + + /// Returns the number of CPUs in the system. + pub fn ax_get_cpu_num() -> usize; } } diff --git a/api/arceos_posix_api/src/imp/sys.rs b/api/arceos_posix_api/src/imp/sys.rs index 4407fdba14..de1b23362a 100644 --- a/api/arceos_posix_api/src/imp/sys.rs +++ b/api/arceos_posix_api/src/imp/sys.rs @@ -15,7 +15,7 @@ pub fn sys_sysconf(name: c_int) -> c_long { // Page size ctypes::_SC_PAGE_SIZE => Ok(PAGE_SIZE_4K), // Number of processors in use - ctypes::_SC_NPROCESSORS_ONLN => Ok(axconfig::plat::CPU_NUM), + ctypes::_SC_NPROCESSORS_ONLN => Ok(axhal::cpu_num()), // Total physical pages ctypes::_SC_PHYS_PAGES => Ok(axhal::mem::total_ram_size() / PAGE_SIZE_4K), // Avaliable physical pages diff --git a/configs/custom/x86_64-pc-oslab.toml b/configs/custom/x86_64-pc-oslab.toml index 51e4f5734b..d218baf35e 100644 --- a/configs/custom/x86_64-pc-oslab.toml +++ b/configs/custom/x86_64-pc-oslab.toml @@ -9,8 +9,9 @@ package = "axplat-x86-pc" # str # Platform configs # [plat] -# Number of CPUs. -cpu-num = 8 # uint +# Maximum number of CPUs. For platforms that do not support runtime CPU number +# detection, it's also the number of CPUs to boot (like this platform). +max-cpu-num = 8 # uint # Base address of the whole physical memory. phys-memory-base = 0 # uint # Size of the whole physical memory. (2G) diff --git a/configs/dummy.toml b/configs/dummy.toml index 877836f9f9..aee052089b 100644 --- a/configs/dummy.toml +++ b/configs/dummy.toml @@ -15,8 +15,9 @@ ticks-per-sec = 100 # uint # [plat] # Platform family. -# Number of CPUs -cpu-num = 1 # uint +# Maximum number of CPUs. For platforms that do not support runtime CPU number +# detection, it's also the number of CPUs to boot. +max-cpu-num = 1 # uint # Base address of the whole physical memory. phys-memory-base = 0 # uint # Size of the whole physical memory. diff --git a/modules/axhal/Cargo.toml b/modules/axhal/Cargo.toml index 3b99de2e5d..bfdd8b4e92 100644 --- a/modules/axhal/Cargo.toml +++ b/modules/axhal/Cargo.toml @@ -36,23 +36,23 @@ memory_addr = "0.4" linkme = { version = "0.3.33", optional = true } page_table_multiarch = { version = "0.5", features = ["copy-from"], optional = true } axcpu = "0.2" -axplat = "0.2" +axplat = "0.3" axlog = { workspace = true } axconfig = { workspace = true } axalloc = { workspace = true, optional = true } [target.'cfg(target_arch = "x86_64")'.dependencies] -axplat-x86-pc = { version = "0.2", optional = true } +axplat-x86-pc = { version = "0.3", optional = true } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64-cpu = "10.0" -axplat-aarch64-qemu-virt = { version = "0.2", optional = true } +axplat-aarch64-qemu-virt = { version = "0.3", optional = true } [target.'cfg(target_arch = "riscv64")'.dependencies] -axplat-riscv64-qemu-virt = { version = "0.2", optional = true } +axplat-riscv64-qemu-virt = { version = "0.3", optional = true } [target.'cfg(target_arch = "loongarch64")'.dependencies] -axplat-loongarch64-qemu-virt = { version = "0.2", optional = true } +axplat-loongarch64-qemu-virt = { version = "0.3", optional = true } [build-dependencies] axconfig = { workspace = true } diff --git a/modules/axhal/build.rs b/modules/axhal/build.rs index 9c6037f382..be7002f358 100644 --- a/modules/axhal/build.rs +++ b/modules/axhal/build.rs @@ -24,7 +24,7 @@ fn gen_linker_script(arch: &str, platform: &str) -> Result<()> { "%KERNEL_BASE%", &format!("{:#x}", axconfig::plat::KERNEL_BASE_VADDR), ); - let ld_content = ld_content.replace("%CPU_NUM%", &format!("{}", axconfig::plat::CPU_NUM)); + let ld_content = ld_content.replace("%CPU_NUM%", &format!("{}", axconfig::plat::MAX_CPU_NUM)); // target///build/axhal-xxxx/out let out_dir = std::env::var("OUT_DIR").unwrap(); diff --git a/modules/axhal/src/dummy.rs b/modules/axhal/src/dummy.rs index 033b4c4408..8dccc072dd 100644 --- a/modules/axhal/src/dummy.rs +++ b/modules/axhal/src/dummy.rs @@ -95,6 +95,10 @@ impl PowerIf for DummyPower { fn system_off() -> ! { unimplemented!() } + + fn cpu_num() -> usize { + 1 + } } #[cfg(feature = "irq")] diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index 85b23bbf53..cb5a1bc171 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -107,6 +107,8 @@ pub use axplat::init::init_later; #[cfg(feature = "smp")] pub use axplat::init::{init_early_secondary, init_later_secondary}; +#[cfg(feature = "smp")] +use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; /// Initializes CPU-local data structures for the primary core. /// @@ -141,3 +143,59 @@ pub fn init_early(cpu_id: usize, arg: usize) { pub fn get_bootarg() -> usize { *BOOT_ARG } + +/// The number of CPUs in the system. Based on the number declared by the +/// platform crate and limited by the configured maximum CPU number. +#[cfg(feature = "smp")] +static CPU_NUM: AtomicUsize = AtomicUsize::new(1); + +/// Gets the number of CPUs running in the system. +/// +/// When SMP is disabled, this function always returns 1. +/// +/// When SMP is enabled, It's the smaller one between the platform-declared CPU +/// number [`axplat::power::cpu_num`] and the configured maximum CPU number +/// `axconfig::plat::MAX_CPU_NUM`. +/// +/// This value is determined during the BSP initialization phase. +pub fn cpu_num() -> usize { + #[cfg(feature = "smp")] + { + // Relaxed is used here for best performance, as this value is only set + // once during initialization and never changed afterwards. + // + // The BSP will always see the correct value because `CPU_NUM` is set by + // itself. + // + // All APs will see the correct value because it is written with + // `Ordering::Release` and read with `Ordering::Acquire`, ensuring + // memory visibility. + CPU_NUM.load(Ordering::Acquire) + } + #[cfg(not(feature = "smp"))] + { + 1 + } +} + +/// Initializes the CPU number information. +pub fn init_cpu_num() { + #[cfg(feature = "smp")] + { + let plat_cpu_num = axplat::power::cpu_num(); + let max_cpu_num = axconfig::plat::MAX_CPU_NUM; + let cpu_num = plat_cpu_num.min(max_cpu_num); + + info!("CPU number: max = {max_cpu_num}, platform = {plat_cpu_num}, use = {cpu_num}",); + + if plat_cpu_num > max_cpu_num { + warn!( + "platform declares more CPUs ({plat_cpu_num}) than configured max ({max_cpu_num}), \ + only the first {max_cpu_num} CPUs will be used." + ); + } + + CPU_NUM.store(cpu_num, Ordering::Release); + } + // No-op for non-SMP builds. +} diff --git a/modules/axipi/src/lib.rs b/modules/axipi/src/lib.rs index a4bc3ec983..bb6bf42910 100644 --- a/modules/axipi/src/lib.rs +++ b/modules/axipi/src/lib.rs @@ -45,7 +45,7 @@ pub fn run_on_cpu>(dest_cpu: usize, callback: T) { pub fn run_on_each_cpu>(callback: T) { info!("Send IPI event to all other CPUs"); let current_cpu_id = this_cpu_id(); - let cpu_num = axconfig::plat::CPU_NUM; + let cpu_num = axhal::cpu_num(); let callback = callback.into(); // Execute callback on current CPU immediately diff --git a/modules/axruntime/Cargo.toml b/modules/axruntime/Cargo.toml index 13abbb59e4..53f96e967b 100644 --- a/modules/axruntime/Cargo.toml +++ b/modules/axruntime/Cargo.toml @@ -37,7 +37,7 @@ axnet = { workspace = true, optional = true } axdisplay = { workspace = true, optional = true } axtask = { workspace = true, optional = true } axipi = { workspace = true, optional = true } -axplat = "0.2" +axplat = "0.3" crate_interface = "0.1" percpu = { version = "0.2", optional = true } diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index 2a46bd4f0c..f31e538d59 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -86,10 +86,11 @@ impl axlog::LogIf for LogIfImpl { use core::sync::atomic::{AtomicUsize, Ordering}; +/// Number of CPUs that have completed initialization. static INITED_CPUS: AtomicUsize = AtomicUsize::new(0); fn is_init_ok() -> bool { - INITED_CPUS.load(Ordering::Acquire) == axconfig::plat::CPU_NUM + INITED_CPUS.load(Ordering::Acquire) == axhal::cpu_num() } /// The main entry point of the ArceOS runtime. @@ -116,14 +117,12 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { target = {}\n\ build_mode = {}\n\ log_level = {}\n\ - smp = {}\n\ ", axconfig::ARCH, axconfig::PLATFORM, option_env!("AX_TARGET").unwrap_or(""), option_env!("AX_MODE").unwrap_or(""), option_env!("AX_LOG").unwrap_or(""), - axconfig::plat::CPU_NUM, ); #[cfg(feature = "rtc")] ax_println!( @@ -157,6 +156,8 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { info!("Initialize platform devices..."); axhal::init_later(cpu_id, arg); + axhal::init_cpu_num(); + #[cfg(feature = "multitask")] axtask::init_scheduler(); diff --git a/modules/axruntime/src/mp.rs b/modules/axruntime/src/mp.rs index 464cfd7326..a1346a690d 100644 --- a/modules/axruntime/src/mp.rs +++ b/modules/axruntime/src/mp.rs @@ -1,19 +1,20 @@ use core::sync::atomic::{AtomicUsize, Ordering}; -use axconfig::{TASK_STACK_SIZE, plat::CPU_NUM}; +use axconfig::{TASK_STACK_SIZE, plat::MAX_CPU_NUM}; use axhal::mem::{VirtAddr, virt_to_phys}; #[unsafe(link_section = ".bss.stack")] -static mut SECONDARY_BOOT_STACK: [[u8; TASK_STACK_SIZE]; CPU_NUM - 1] = - [[0; TASK_STACK_SIZE]; CPU_NUM - 1]; +static mut SECONDARY_BOOT_STACK: [[u8; TASK_STACK_SIZE]; MAX_CPU_NUM - 1] = + [[0; TASK_STACK_SIZE]; MAX_CPU_NUM - 1]; static ENTERED_CPUS: AtomicUsize = AtomicUsize::new(1); #[allow(clippy::absurd_extreme_comparisons)] pub fn start_secondary_cpus(primary_cpu_id: usize) { let mut logic_cpu_id = 0; - for i in 0..CPU_NUM { - if i != primary_cpu_id && logic_cpu_id < CPU_NUM - 1 { + let cpu_num = axhal::cpu_num(); + for i in 0..cpu_num { + if i != primary_cpu_id && logic_cpu_id < cpu_num - 1 { let stack_top = virt_to_phys(VirtAddr::from(unsafe { SECONDARY_BOOT_STACK[logic_cpu_id].as_ptr_range().end as usize })); diff --git a/modules/axtask/Cargo.toml b/modules/axtask/Cargo.toml index 138519e0cc..58a97edfe8 100644 --- a/modules/axtask/Cargo.toml +++ b/modules/axtask/Cargo.toml @@ -16,7 +16,6 @@ multitask = [ "dep:axconfig", "dep:percpu", "dep:kspin", - "dep:lazyinit", "dep:memory_addr", "dep:axsched", "dep:timer_list", diff --git a/modules/axtask/src/api.rs b/modules/axtask/src/api.rs index 1e3fdca726..80f1d8dcfb 100644 --- a/modules/axtask/src/api.rs +++ b/modules/axtask/src/api.rs @@ -17,7 +17,7 @@ pub use crate::wait_queue::WaitQueue; pub type AxTaskRef = Arc; /// The wrapper type for [`cpumask::CpuMask`] with SMP configuration. -pub type AxCpuMask = cpumask::CpuMask<{ axconfig::plat::CPU_NUM }>; +pub type AxCpuMask = cpumask::CpuMask<{ axconfig::plat::MAX_CPU_NUM }>; cfg_if::cfg_if! { if #[cfg(feature = "sched-rr")] { @@ -72,6 +72,10 @@ pub fn current() -> CurrentTask { pub fn init_scheduler() { info!("Initialize scheduling..."); + // Initialize the cpu count information. + init_cpu_mask_full(); + + // Initialize the run queue. crate::run_queue::init(); #[cfg(feature = "irq")] crate::timers::init(); @@ -79,6 +83,27 @@ pub fn init_scheduler() { info!(" use {} scheduler.", Scheduler::scheduler_name()); } +/// The full CPU mask of the system. +static CPU_MASK_FULL: lazyinit::LazyInit = lazyinit::LazyInit::new(); + +/// Gets the cpu count information and initializes related data structures. +fn init_cpu_mask_full() { + let cpu_num = axhal::cpu_num(); + let mut cpumask = AxCpuMask::new(); + for cpu_id in 0..cpu_num { + cpumask.set(cpu_id, true); + } + + CPU_MASK_FULL.call_once(|| cpumask); +} + +pub(crate) fn cpu_mask_full() -> AxCpuMask { + CPU_MASK_FULL + .get() + .expect("CPU mask not initialized") + .clone() +} + /// Initializes the task scheduler for secondary CPUs. pub fn init_scheduler_secondary() { crate::run_queue::init_secondary(); diff --git a/modules/axtask/src/run_queue.rs b/modules/axtask/src/run_queue.rs index a907b4a2a9..ec5bababa8 100644 --- a/modules/axtask/src/run_queue.rs +++ b/modules/axtask/src/run_queue.rs @@ -48,8 +48,8 @@ percpu_static! { /// Access to this variable is marked as `unsafe` because it contains `MaybeUninit` references, /// which require careful handling to avoid undefined behavior. The array should be fully /// initialized before being accessed to ensure safe usage. -static mut RUN_QUEUES: [MaybeUninit<&'static mut AxRunQueue>; axconfig::plat::CPU_NUM] = - [ARRAY_REPEAT_VALUE; axconfig::plat::CPU_NUM]; +static mut RUN_QUEUES: [MaybeUninit<&'static mut AxRunQueue>; axconfig::plat::MAX_CPU_NUM] = + [ARRAY_REPEAT_VALUE; axconfig::plat::MAX_CPU_NUM]; #[allow(clippy::declare_interior_mutable_const)] // It's ok because it's used only for initialization `RUN_QUEUES`. const ARRAY_REPEAT_VALUE: MaybeUninit<&'static mut AxRunQueue> = MaybeUninit::uninit(); @@ -94,7 +94,8 @@ pub(crate) fn current_run_queue() -> CurrentRunQueueRef<'static, G /// This function will panic if `cpu_mask` is empty, indicating that there are no available CPUs for task execution. /// #[cfg(feature = "smp")] -// The modulo operation is safe here because `axconfig::plat::CPU_NUM` is always greater than 1 with "smp" enabled. +// The modulo operation is safe here because `axhal::cpu_num()` is expected to be greater than 1 in SMP mode. +// If not, index selection logic would not be meaningful. #[allow(clippy::modulo_one)] #[inline] fn select_run_queue_index(cpumask: AxCpuMask) -> usize { @@ -105,7 +106,7 @@ fn select_run_queue_index(cpumask: AxCpuMask) -> usize { // Round-robin selection of the run queue index. loop { - let index = RUN_QUEUE_INDEX.fetch_add(1, Ordering::SeqCst) % axconfig::plat::CPU_NUM; + let index = RUN_QUEUE_INDEX.fetch_add(1, Ordering::SeqCst) % axhal::cpu_num(); if cpumask.get(index) { return index; } diff --git a/modules/axtask/src/task.rs b/modules/axtask/src/task.rs index 603717bfd9..bdc40c7338 100644 --- a/modules/axtask/src/task.rs +++ b/modules/axtask/src/task.rs @@ -224,6 +224,8 @@ impl TaskInner { // private methods impl TaskInner { fn new_common(id: TaskId, name: String) -> Self { + let cpumask = crate::api::cpu_mask_full(); + Self { id, name, @@ -232,7 +234,7 @@ impl TaskInner { entry: None, state: AtomicU8::new(TaskState::Ready as u8), // By default, the task is allowed to run on all CPUs. - cpumask: SpinNoIrq::new(AxCpuMask::full()), + cpumask, in_wait_queue: AtomicBool::new(false), #[cfg(feature = "irq")] timer_ticket_id: AtomicU64::new(0), diff --git a/scripts/make/config.mk b/scripts/make/config.mk index 02d69a99ea..f780a4f27d 100644 --- a/scripts/make/config.mk +++ b/scripts/make/config.mk @@ -7,11 +7,12 @@ config_args := \ -o "$(OUT_CONFIG)" ifneq ($(SMP),) - config_args += -w 'plat.cpu-num=$(SMP)' + config_args += -w 'plat.max-cpu-num=$(SMP)' else - SMP := $(shell axconfig-gen $(PLAT_CONFIG) -r plat.cpu-num 2>/dev/null) + SMP := $(shell axconfig-gen $(PLAT_CONFIG) -r plat.max-cpu-num 2>/dev/null) ifeq ($(SMP),) - $(error "`plat.cpu-num` is not defined in the platform configuration file") + $(error "`plat.max-cpu-num` is not defined in the platform configuration file, \ + this option must be specified even for platforms with runtime CPU detection.") endif endif diff --git a/ulib/axstd/src/thread/mod.rs b/ulib/axstd/src/thread/mod.rs index 996a2094ad..cba228bd31 100644 --- a/ulib/axstd/src/thread/mod.rs +++ b/ulib/axstd/src/thread/mod.rs @@ -46,6 +46,6 @@ pub fn sleep_until(deadline: arceos_api::time::AxTimeValue) { /// Here we directly return the number of available logical CPUs, representing /// the theoretical maximum parallelism. pub fn available_parallelism() -> crate::io::Result> { - NonZero::new(arceos_api::modules::axconfig::plat::CPU_NUM) + NonZero::new(arceos_api::sys::ax_get_cpu_num()) .ok_or_else(|| panic!("No available CPUs found, cannot determine parallelism")) } From 68499d38ab362ed599c7d1293cb20d70a85a60a6 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 01:27:51 +0800 Subject: [PATCH 2/7] update axplat_crates for arceos-helloworld-myplat --- Cargo.lock | 160 +++++--------------------- examples/helloworld-myplat/Cargo.toml | 14 +-- 2 files changed, 35 insertions(+), 139 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 203d24e78b..1cf9ef8147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,11 +119,11 @@ version = "0.1.0" dependencies = [ "axplat-aarch64-bsta1000b", "axplat-aarch64-phytium-pi", - "axplat-aarch64-qemu-virt 0.2.0", + "axplat-aarch64-qemu-virt", "axplat-aarch64-raspi", - "axplat-loongarch64-qemu-virt 0.2.0", - "axplat-riscv64-qemu-virt 0.2.0", - "axplat-x86-pc 0.2.0", + "axplat-loongarch64-qemu-virt", + "axplat-riscv64-qemu-virt", + "axplat-x86-pc", "axstd", "cfg-if", ] @@ -502,11 +502,11 @@ dependencies = [ "axconfig", "axcpu", "axlog", - "axplat 0.3.0", - "axplat-aarch64-qemu-virt 0.3.0", - "axplat-loongarch64-qemu-virt 0.3.0", - "axplat-riscv64-qemu-virt 0.3.0", - "axplat-x86-pc 0.3.0", + "axplat", + "axplat-aarch64-qemu-virt", + "axplat-loongarch64-qemu-virt", + "axplat-riscv64-qemu-virt", + "axplat-x86-pc", "cfg-if", "heapless 0.8.0", "kernel_guard", @@ -604,21 +604,6 @@ dependencies = [ "lazyinit", ] -[[package]] -name = "axplat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4de04c54b63bf2ca1ff202733d2516da49d7779649cdb2f9c4ecf22909e6810" -dependencies = [ - "axplat-macros", - "bitflags 2.9.2", - "const-str", - "crate_interface", - "handler_table", - "kspin", - "memory_addr", -] - [[package]] name = "axplat" version = "0.3.0" @@ -636,40 +621,20 @@ dependencies = [ [[package]] name = "axplat-aarch64-bsta1000b" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af884a8e67b199c395d634e0a2fa9cd954279dd9abe9e672b84e833506f8466c" +checksum = "c2768d42cdd829ca385e4c00d048011448d6203a2982e0e2fb949a0c2cca7e5f" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.2.0", - "axplat-aarch64-peripherals 0.2.0", + "axplat", + "axplat-aarch64-peripherals", "dw_apb_uart", "kspin", "log", "page_table_entry", ] -[[package]] -name = "axplat-aarch64-peripherals" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9a6548290a150059eb2ae015dc58d9b3d652461760327b95a490666129974c" -dependencies = [ - "aarch64-cpu 10.0.0", - "arm-gic-driver", - "arm_pl011", - "arm_pl031", - "axcpu", - "axplat 0.2.0", - "int_ratio", - "kspin", - "lazyinit", - "log", - "page_table_entry", - "spin 0.10.0", -] - [[package]] name = "axplat-aarch64-peripherals" version = "0.3.0" @@ -681,7 +646,7 @@ dependencies = [ "arm_pl011", "arm_pl031", "axcpu", - "axplat 0.3.0", + "axplat", "int_ratio", "kspin", "lazyinit", @@ -692,28 +657,14 @@ dependencies = [ [[package]] name = "axplat-aarch64-phytium-pi" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c893f78d02cfa594bbe7f5880e69c610f79c119a28a4c2d095dfca95287f0e" -dependencies = [ - "axconfig-macros", - "axcpu", - "axplat 0.2.0", - "axplat-aarch64-peripherals 0.2.0", - "log", - "page_table_entry", -] - -[[package]] -name = "axplat-aarch64-qemu-virt" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f03bfe81ebc5b2f567eecadcab221107b90f394485dd0da39334411a676d81a" +checksum = "c210511ecaab4448142413197df3ce052aa1f0c93664c952b6bffb1c3f7e02c1" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.2.0", - "axplat-aarch64-peripherals 0.2.0", + "axplat", + "axplat-aarch64-peripherals", "log", "page_table_entry", ] @@ -726,44 +677,27 @@ checksum = "8a67e4110907e19c3ab1353e4386f4656aab395c83656cfee22ba6b49ed35250" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.3.0", - "axplat-aarch64-peripherals 0.3.0", + "axplat", + "axplat-aarch64-peripherals", "log", "page_table_entry", ] [[package]] name = "axplat-aarch64-raspi" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48df7f92caad3148cceff163c7988a0eee95d5e3523ec7e0ef0d9e85255ca98a" +checksum = "b0328561d8130066093fec6f66b0fb45e8063e8832f66d36e7eb9569d2ed2d89" dependencies = [ "aarch64-cpu 10.0.0", "axconfig-macros", "axcpu", - "axplat 0.2.0", - "axplat-aarch64-peripherals 0.2.0", + "axplat", + "axplat-aarch64-peripherals", "log", "page_table_entry", ] -[[package]] -name = "axplat-loongarch64-qemu-virt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c404064c74824b2c509e1d84f2ae0cbd9240a3274fb4053dc81b9ad120b5962" -dependencies = [ - "axconfig-macros", - "axcpu", - "axplat 0.2.0", - "kspin", - "lazyinit", - "log", - "loongArch64", - "ns16550a", - "page_table_entry", -] - [[package]] name = "axplat-loongarch64-qemu-virt" version = "0.3.0" @@ -772,7 +706,7 @@ checksum = "00a0c4b0a25488e6a9b536a55fae2153d14ef40bd931b2c28bf387a95ad3fb80" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.3.0", + "axplat", "chrono", "kspin", "lazyinit", @@ -793,20 +727,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "axplat-riscv64-qemu-virt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d95d76dfa65d75d07380ac13692c3b0c5bd6ae5b68df7bbede1f2e7181027a" -dependencies = [ - "axconfig-macros", - "axcpu", - "axplat 0.2.0", - "log", - "riscv", - "sbi-rt", -] - [[package]] name = "axplat-riscv64-qemu-virt" version = "0.3.0" @@ -815,37 +735,13 @@ checksum = "fb75b0b52fd2289ec461a3ea3aba978cb943fb07fb023d5edc2c8efe079eb724" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.3.0", + "axplat", "log", "riscv", "riscv_goldfish", "sbi-rt", ] -[[package]] -name = "axplat-x86-pc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aef32b01b5b7e87e9f69933b64b704bc5d731adda2cdd24fc0a29cf0c359211" -dependencies = [ - "axconfig-macros", - "axcpu", - "axplat 0.2.0", - "bitflags 2.9.2", - "heapless 0.9.1", - "int_ratio", - "kspin", - "lazyinit", - "log", - "multiboot", - "percpu", - "raw-cpuid 11.5.0", - "uart_16550", - "x2apic", - "x86", - "x86_64", -] - [[package]] name = "axplat-x86-pc" version = "0.3.0" @@ -854,7 +750,7 @@ checksum = "d3488a8857c3e66da47a320e4c6ebba10f6218481e31ca3f2e00f927e1ad68c1" dependencies = [ "axconfig-macros", "axcpu", - "axplat 0.3.0", + "axplat", "bitflags 2.9.2", "heapless 0.9.1", "int_ratio", @@ -885,7 +781,7 @@ dependencies = [ "axlog", "axmm", "axnet", - "axplat 0.3.0", + "axplat", "axtask", "chrono", "crate_interface", diff --git a/examples/helloworld-myplat/Cargo.toml b/examples/helloworld-myplat/Cargo.toml index 2fa9c1fc77..c835011ced 100644 --- a/examples/helloworld-myplat/Cargo.toml +++ b/examples/helloworld-myplat/Cargo.toml @@ -18,16 +18,16 @@ cfg-if = "1.0" axstd = { workspace = true, features = ["myplat"], optional = true } [target.'cfg(target_arch = "x86_64")'.dependencies] -axplat-x86-pc = { version = "0.2", features = ["smp", "irq"], optional = true } +axplat-x86-pc = { version = "0.3", features = ["smp", "irq"], optional = true } [target.'cfg(target_arch = "aarch64")'.dependencies] -axplat-aarch64-qemu-virt = { version = "0.2", features = ["smp", "irq"], optional = true } -axplat-aarch64-raspi = { version = "0.2", features = ["smp", "irq"], optional = true } -axplat-aarch64-bsta1000b = { version = "0.2", features = ["smp", "irq"], optional = true } -axplat-aarch64-phytium-pi = { version = "0.2", features = ["smp", "irq"], optional = true } +axplat-aarch64-qemu-virt = { version = "0.3", features = ["smp", "irq"], optional = true } +axplat-aarch64-raspi = { version = "0.3", features = ["smp", "irq"], optional = true } +axplat-aarch64-bsta1000b = { version = "0.3", features = ["smp", "irq"], optional = true } +axplat-aarch64-phytium-pi = { version = "0.3", features = ["smp", "irq"], optional = true } [target.'cfg(target_arch = "riscv64")'.dependencies] -axplat-riscv64-qemu-virt = { version = "0.2", features = ["smp", "irq"], optional = true } +axplat-riscv64-qemu-virt = { version = "0.3", features = ["smp", "irq"], optional = true } [target.'cfg(target_arch = "loongarch64")'.dependencies] -axplat-loongarch64-qemu-virt = { version = "0.2", features = ["smp", "irq"], optional = true } \ No newline at end of file +axplat-loongarch64-qemu-virt = { version = "0.3", features = ["smp", "irq"], optional = true } \ No newline at end of file From 138dcb538063885871282a61591656b31c79cb55 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 01:33:31 +0800 Subject: [PATCH 3/7] fix errors after cherry-picking --- Makefile | 4 ++-- modules/axhal/src/lib.rs | 4 ++-- modules/axtask/Cargo.toml | 2 +- modules/axtask/src/task.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c1a2853a0f..81189c725a 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ # - `MYPLAT`: Package name of the target platform crate. # - `PLAT_CONFIG`: Path to the platform configuration file. # - `SMP`: Override maximum CPU number specified in the platform config. For -# statically configured platforms, this is also the number of CPUs to boot -# and for platforms with runtime CPU detection, this is the upper limit of +# statically configured platforms, this is also the number of CPUs to boot +# and for platforms with runtime CPU detection, this is the upper limit of # CPUs. # - `MODE`: Build mode: release, debug # - `LOG:` Logging level: warn, error, info, debug, trace diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index cb5a1bc171..40516501b2 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -108,7 +108,7 @@ pub use axplat::init::init_later; #[cfg(feature = "smp")] pub use axplat::init::{init_early_secondary, init_later_secondary}; #[cfg(feature = "smp")] -use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use core::sync::atomic::{AtomicUsize, Ordering}; /// Initializes CPU-local data structures for the primary core. /// @@ -153,7 +153,7 @@ static CPU_NUM: AtomicUsize = AtomicUsize::new(1); /// /// When SMP is disabled, this function always returns 1. /// -/// When SMP is enabled, It's the smaller one between the platform-declared CPU +/// When SMP is enabled, it's the smaller one between the platform-declared CPU /// number [`axplat::power::cpu_num`] and the configured maximum CPU number /// `axconfig::plat::MAX_CPU_NUM`. /// diff --git a/modules/axtask/Cargo.toml b/modules/axtask/Cargo.toml index 58a97edfe8..a68cc3a169 100644 --- a/modules/axtask/Cargo.toml +++ b/modules/axtask/Cargo.toml @@ -41,7 +41,7 @@ axhal = { workspace = true } axconfig = { workspace = true, optional = true } percpu = { version = "0.2", optional = true } kspin = { version = "0.1", optional = true } -lazyinit = { version = "0.2", optional = true } +lazyinit = { version = "0.2" } memory_addr = { version = "0.4", optional = true } timer_list = { version = "0.1", optional = true } kernel_guard = { version = "0.1", optional = true } diff --git a/modules/axtask/src/task.rs b/modules/axtask/src/task.rs index bdc40c7338..403488012a 100644 --- a/modules/axtask/src/task.rs +++ b/modules/axtask/src/task.rs @@ -234,7 +234,7 @@ impl TaskInner { entry: None, state: AtomicU8::new(TaskState::Ready as u8), // By default, the task is allowed to run on all CPUs. - cpumask, + cpumask: SpinNoIrq::new(cpumask), in_wait_queue: AtomicBool::new(false), #[cfg(feature = "irq")] timer_ticket_id: AtomicU64::new(0), From 99047aa29494ae9be44de5b62029fa241fe0fb34 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 01:45:16 +0800 Subject: [PATCH 4/7] add `smp = {}` output for test purpose --- modules/axhal/src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index 40516501b2..73af462813 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -34,6 +34,10 @@ #[macro_use] extern crate log; +#[allow(unused_imports)] +#[macro_use] +extern crate axlog; + #[allow(unused_imports)] #[macro_use] extern crate memory_addr; @@ -187,6 +191,7 @@ pub fn init_cpu_num() { let cpu_num = plat_cpu_num.min(max_cpu_num); info!("CPU number: max = {max_cpu_num}, platform = {plat_cpu_num}, use = {cpu_num}",); + ax_println!("smp = {}", cpu_num); // for test purposes if plat_cpu_num > max_cpu_num { warn!( @@ -197,5 +202,8 @@ pub fn init_cpu_num() { CPU_NUM.store(cpu_num, Ordering::Release); } - // No-op for non-SMP builds. + #[cfg(not(feature = "smp"))] + { + ax_println!("smp = 1"); // for test purposes + } } From ac6f352df04083ff94d199750867171dd2da106d Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 12:43:49 +0800 Subject: [PATCH 5/7] fix an out-dated comment --- modules/axhal/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index 73af462813..cc3e78e361 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -165,15 +165,15 @@ static CPU_NUM: AtomicUsize = AtomicUsize::new(1); pub fn cpu_num() -> usize { #[cfg(feature = "smp")] { - // Relaxed is used here for best performance, as this value is only set - // once during initialization and never changed afterwards. - // // The BSP will always see the correct value because `CPU_NUM` is set by // itself. // // All APs will see the correct value because it is written with // `Ordering::Release` and read with `Ordering::Acquire`, ensuring // memory visibility. + // + // Acquire may result in a performance penalty, but this function is not + // expected to be called frequently in normal operation. CPU_NUM.load(Ordering::Acquire) } #[cfg(not(feature = "smp"))] From e0adfade2472fedaeb8b597d88212241be928053 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 14:10:50 +0800 Subject: [PATCH 6/7] move `init_cpu_num` into `init_later` --- modules/axhal/src/lib.rs | 17 +++++++++++------ modules/axruntime/src/lib.rs | 2 -- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index cc3e78e361..2b200437b8 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -107,7 +107,6 @@ pub mod context { } pub use axcpu::asm; -pub use axplat::init::init_later; #[cfg(feature = "smp")] pub use axplat::init::{init_early_secondary, init_later_secondary}; @@ -131,10 +130,6 @@ pub fn init_percpu_secondary(cpu_id: usize) { self::percpu::init_secondary(cpu_id); } -use lazyinit::LazyInit; - -static BOOT_ARG: LazyInit = LazyInit::new(); - /// Initializes the platform and boot argument. /// This function should be called as early as possible. pub fn init_early(cpu_id: usize, arg: usize) { @@ -142,6 +137,16 @@ pub fn init_early(cpu_id: usize, arg: usize) { axplat::init::init_early(cpu_id, arg); } +/// Initializes the platform later stage. +pub fn init_later(cpu_id: usize, arg: usize) { + axplat::init::init_later(cpu_id, arg); + init_cpu_num(); +} + +use lazyinit::LazyInit; + +static BOOT_ARG: LazyInit = LazyInit::new(); + /// Returns the boot argument. /// This is typically the device tree blob address passed from the bootloader. pub fn get_bootarg() -> usize { @@ -183,7 +188,7 @@ pub fn cpu_num() -> usize { } /// Initializes the CPU number information. -pub fn init_cpu_num() { +fn init_cpu_num() { #[cfg(feature = "smp")] { let plat_cpu_num = axplat::power::cpu_num(); diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index f31e538d59..3f9a6b9b30 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -156,8 +156,6 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { info!("Initialize platform devices..."); axhal::init_later(cpu_id, arg); - axhal::init_cpu_num(); - #[cfg(feature = "multitask")] axtask::init_scheduler(); From 9d434c44b8984f9fbe00517052fcfa32de3d43f4 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Fri, 19 Dec 2025 14:15:21 +0800 Subject: [PATCH 7/7] cache `cpu_num` in select_run_queue_index --- modules/axtask/src/run_queue.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/axtask/src/run_queue.rs b/modules/axtask/src/run_queue.rs index ec5bababa8..d19452ab40 100644 --- a/modules/axtask/src/run_queue.rs +++ b/modules/axtask/src/run_queue.rs @@ -105,8 +105,9 @@ fn select_run_queue_index(cpumask: AxCpuMask) -> usize { assert!(!cpumask.is_empty(), "No available CPU for task execution"); // Round-robin selection of the run queue index. + let cpu_num = axhal::cpu_num(); loop { - let index = RUN_QUEUE_INDEX.fetch_add(1, Ordering::SeqCst) % axhal::cpu_num(); + let index = RUN_QUEUE_INDEX.fetch_add(1, Ordering::SeqCst) % cpu_num; if cpumask.get(index) { return index; }