Safe get-percpu wrapper and warnings fixes.

This commit is contained in:
4lDO2
2026-09-05 07:16:38 -06:00
committed by Jeremy Soller
parent a2ee203ee5
commit 5c796a0ac6
9 changed files with 63 additions and 100 deletions
-17
View File
@@ -258,23 +258,6 @@ impl Context {
} }
} }
/// Unblock context, and return true if it was blocked before being marked runnable
pub fn unblock(&mut self) -> bool {
if self.unblock_no_ipi() {
// TODO: Only send IPI if currently running?
if let Some(cpu_id) = self.cpu_id
&& cpu_id != crate::cpu_id()
{
// Send IPI if not on current CPU
ipi(IpiKind::Wakeup, IpiTarget::Other);
}
true
} else {
false
}
}
/// Unblock context without IPI, and return true if it was blocked before being marked runnable /// Unblock context without IPI, and return true if it was blocked before being marked runnable
pub fn unblock_no_ipi(&mut self) -> bool { pub fn unblock_no_ipi(&mut self) -> bool {
if self.status.is_soft_blocked() { if self.status.is_soft_blocked() {
+17 -29
View File
@@ -18,7 +18,7 @@ use crate::{
cpu_stats::CpuStatsData, cpu_stats::CpuStatsData,
ipi::{ipi, IpiKind, IpiTarget}, ipi::{ipi, IpiKind, IpiTarget},
memory::{RmmA, RmmArch, TableKind}, memory::{RmmA, RmmArch, TableKind},
percpu::PercpuBlock, percpu::{get_percpu_block, PercpuBlock},
sync::{ sync::{
ArcRwLockWriteGuard, CleanLockToken, LockToken, Mutex, MutexGuard, RwLock, RwLockReadGuard, ArcRwLockWriteGuard, CleanLockToken, LockToken, Mutex, MutexGuard, RwLock, RwLockReadGuard,
RwLockWriteGuard, L0, L1, L2, L3, L4, RwLockWriteGuard, L0, L1, L2, L3, L4,
@@ -27,8 +27,6 @@ use crate::{
Ordering, Ordering,
}; };
use crate::percpu::ALL_PERCPU_BLOCKS;
use self::context::Kstack; use self::context::Kstack;
pub use self::{ pub use self::{
context::{BorrowedHtBuf, Context, Status}, context::{BorrowedHtBuf, Context, Status},
@@ -144,21 +142,17 @@ pub fn wakeup_context(
let target_cpu = cpu_id.unwrap_or(curr_cpu); let target_cpu = cpu_id.unwrap_or(curr_cpu);
if target_cpu != curr_cpu { if target_cpu != curr_cpu
if let Some(percpu) = unsafe { && let Some(percpu) = get_percpu_block(target_cpu)
ALL_PERCPU_BLOCKS[target_cpu.get() as usize] {
.load(Ordering::Acquire) // non-local wakeup
.as_ref() percpu
} { .switch_internals
// non-local wakeup .ipi_context_wakeup_list
percpu .lock(token.token())
.switch_internals .push(weak);
.ipi_context_wakeup_list ipi(IpiKind::Wakeup, IpiTarget::Other);
.lock(token.token()) return;
.push(weak);
ipi(IpiKind::Wakeup, IpiTarget::Other);
return;
}
} }
// local wakeup // local wakeup
@@ -393,17 +387,11 @@ pub fn get_contexts_stats(token: &mut CleanLockToken) -> [usize; 5] {
let mut switches = 0; let mut switches = 0;
let mut syscall_switches = 0; let mut syscall_switches = 0;
for i in 0..crate::cpu_count() { for percpu in crate::percpu::all_percpu_blocks() {
if let Some(percpu) = unsafe { running += percpu.switch_internals.run_queue.lock().queue.len();
ALL_PERCPU_BLOCKS[i as usize] let data = CpuStatsData::from(&percpu.stats);
.load(Ordering::Acquire) switches += data.context_switches as usize;
.as_ref() syscall_switches += data.syscall_switches as usize;
} {
running += percpu.switch_internals.run_queue.lock().queue.len();
let data = CpuStatsData::from(&percpu.stats);
switches += data.context_switches as usize;
syscall_switches += data.syscall_switches as usize;
}
} }
let blocked = alive.saturating_sub(running); let blocked = alive.saturating_sub(running);
+3 -11
View File
@@ -9,7 +9,7 @@ use crate::{
}, },
cpu_set::LogicalCpuId, cpu_set::LogicalCpuId,
cpu_stats::{self, CpuState}, cpu_stats::{self, CpuState},
percpu::{self, PercpuBlock, ALL_PERCPU_BLOCKS}, percpu::{self, get_percpu_block, PercpuBlock},
sync::{ArcRwLockWriteGuard, CleanLockToken, Mutex, L4}, sync::{ArcRwLockWriteGuard, CleanLockToken, Mutex, L4},
}; };
use alloc::{ use alloc::{
@@ -697,11 +697,7 @@ fn select_next_context(
continue; continue;
} }
if let Some(p) = unsafe { if let Some(p) = get_percpu_block(LogicalCpuId::new(i as u32)) {
ALL_PERCPU_BLOCKS[i as usize]
.load(Ordering::Acquire)
.as_ref()
} {
let neighbour_len = p.switch_internals.queue_len.load(Ordering::Relaxed); let neighbour_len = p.switch_internals.queue_len.load(Ordering::Relaxed);
if neighbour_len > max_neighbour { if neighbour_len > max_neighbour {
@@ -723,11 +719,7 @@ fn select_next_context(
if target_cpu == curr_cpu { if target_cpu == curr_cpu {
continue; continue;
} }
let Some(target_percpu) = (unsafe { let Some(target_percpu) = get_percpu_block(LogicalCpuId::new(target_cpu)) else {
ALL_PERCPU_BLOCKS[target_cpu as usize]
.load(Ordering::Acquire)
.as_ref()
}) else {
continue; continue;
}; };
+23 -29
View File
@@ -3,7 +3,7 @@ use core::{mem, ops::Add, ptr::write_bytes, slice};
use crate::{ use crate::{
acpi, acpi,
cpu_set::{LogicalCpuId, LogicalCpuSet, MAX_CPU_COUNT}, cpu_set::{LogicalCpuId, LogicalCpuSet, MAX_CPU_COUNT},
percpu::{self, ALL_PERCPU_BLOCKS}, percpu,
sync::{CleanLockToken, Mutex, L0}, sync::{CleanLockToken, Mutex, L0},
}; };
use alloc::{sync::Arc, vec::Vec}; use alloc::{sync::Arc, vec::Vec};
@@ -116,36 +116,30 @@ pub fn init_arch() {
numa_nodes[memory.node_id as usize].memories.enable_index(i); numa_nodes[memory.node_id as usize].memories.enable_index(i);
} }
for cpu_ptr in percpu::ALL_PERCPU_BLOCKS.as_ref() { for cpu in percpu::all_percpu_blocks() {
if let Some(cpu) = #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe { cpu_ptr.load(core::sync::atomic::Ordering::Relaxed).as_mut() } let cpu_id = cpu
{ .misc_arch_info
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] .apic_id_opt
let cpu_id = cpu .get()
.misc_arch_info .map(|e| e.get())
.apic_id_opt .unwrap();
.get()
.map(|e| e.get())
.unwrap();
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
let cpu_id = 0; // TODO let cpu_id = 0; // TODO
let n = numa_nodes let n = numa_nodes
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(i, node)| { .find_map(|(i, node)| {
if node.cpus & 1u128 << cpu_id != 0 { if node.cpus & 1u128 << cpu_id != 0 {
Some((i, node)) Some((i, node))
} else { } else {
None None
} }
}) })
.map(|(i, node)| (i as u32, node)); .map(|(i, node)| (i as u32, node));
cpu.numa_node.set(n); cpu.numa_node.set(n);
} else {
break;
}
} }
NUMA_NODES.call_once(|| numa_nodes); NUMA_NODES.call_once(|| numa_nodes);
+16 -8
View File
@@ -25,6 +25,8 @@ use crate::{
}; };
/// The percpu block, that stored all percpu variables. /// The percpu block, that stored all percpu variables.
// TODO: consider splitting this struct into a !Sync part (which safe code is not allowed to get
// references to for other hw threads' blocks) and a Sync part
pub struct PercpuBlock { pub struct PercpuBlock {
/// A unique immutable number that identifies the current CPU - used for scheduling /// A unique immutable number that identifies the current CPU - used for scheduling
pub cpu_id: LogicalCpuId, pub cpu_id: LogicalCpuId,
@@ -57,15 +59,25 @@ pub struct PercpuBlock {
pub static ALL_PERCPU_BLOCKS: [AtomicPtr<PercpuBlock>; MAX_CPU_COUNT as usize] = pub static ALL_PERCPU_BLOCKS: [AtomicPtr<PercpuBlock>; MAX_CPU_COUNT as usize] =
[const { AtomicPtr::new(core::ptr::null_mut()) }; MAX_CPU_COUNT as usize]; [const { AtomicPtr::new(core::ptr::null_mut()) }; MAX_CPU_COUNT as usize];
#[inline]
pub fn get_percpu_block(idx: LogicalCpuId) -> Option<&'static PercpuBlock> {
let ptr = ALL_PERCPU_BLOCKS
.get(idx.get() as usize)?
.load(Ordering::Relaxed);
unsafe { ptr.as_ref() }
}
pub fn all_percpu_blocks() -> impl Iterator<Item = &'static PercpuBlock> {
(0..ALL_PERCPU_BLOCKS.len()).filter_map(|i| get_percpu_block(LogicalCpuId::new(i as u32)))
}
#[allow(unused)] #[allow(unused)]
pub unsafe fn init_tlb_shootdown(id: LogicalCpuId, block: *mut PercpuBlock) { pub unsafe fn init_tlb_shootdown(id: LogicalCpuId, block: *mut PercpuBlock) {
ALL_PERCPU_BLOCKS[id.get() as usize].store(block, Ordering::Release) ALL_PERCPU_BLOCKS[id.get() as usize].store(block, Ordering::Release)
} }
pub fn get_all_stats() -> Vec<(LogicalCpuId, CpuStatsData)> { pub fn get_all_stats() -> Vec<(LogicalCpuId, CpuStatsData)> {
let mut res = ALL_PERCPU_BLOCKS let mut res = (0..ALL_PERCPU_BLOCKS.len())
.iter() .filter_map(|i| get_percpu_block(LogicalCpuId::new(i as u32)))
.filter_map(|block| unsafe { block.load(Ordering::Relaxed).as_ref() })
.map(|block| { .map(|block| {
let stats = &block.stats; let stats = &block.stats;
(block.cpu_id, stats.into()) (block.cpu_id, stats.into())
@@ -86,11 +98,7 @@ pub fn shootdown_tlb_ipi(target: Option<LogicalCpuId>) {
let my_percpublock = PercpuBlock::current(); let my_percpublock = PercpuBlock::current();
assert_ne!(target, my_percpublock.cpu_id); assert_ne!(target, my_percpublock.cpu_id);
let Some(percpublock) = (unsafe { let Some(percpublock) = (get_percpu_block(target)) else {
ALL_PERCPU_BLOCKS[target.get() as usize]
.load(Ordering::Acquire)
.as_ref()
}) else {
warn!("Trying to TLB shootdown a CPU that doesn't exist or isn't initialized."); warn!("Trying to TLB shootdown a CPU that doesn't exist or isn't initialized.");
return; return;
}; };
+1 -2
View File
@@ -23,11 +23,10 @@ use crate::{
GrantFileRef, MmapMode, PageSpan, UnmapVec, DANGLING, GrantFileRef, MmapMode, PageSpan, UnmapVec, DANGLING,
}, },
unblock_context, wakeup_context, BorrowedHtBuf, ContextLock, PreemptGuard, PreemptGuardL1, unblock_context, wakeup_context, BorrowedHtBuf, ContextLock, PreemptGuard, PreemptGuardL1,
Status, WeakContextRef, Status,
}, },
event, event,
memory::{Frame, Page, VirtualAddress, PAGE_SIZE}, memory::{Frame, Page, VirtualAddress, PAGE_SIZE},
percpu::PercpuBlock,
scheme::SchemeId, scheme::SchemeId,
sync::{CleanLockToken, LockToken, Mutex, RwLock, WaitQueue, L1}, sync::{CleanLockToken, LockToken, Mutex, RwLock, WaitQueue, L1},
syscall::{ syscall::{
+1 -1
View File
@@ -13,7 +13,7 @@ use crate::{
}, },
}, },
memory::{Page, VirtualAddress, PAGE_SIZE}, memory::{Page, VirtualAddress, PAGE_SIZE},
scheme::{self, FileHandle, KernelScheme, OpenResult, StrOrBytes}, scheme::{FileHandle, KernelScheme, OpenResult, StrOrBytes},
sync::{CleanLockToken, RwLock}, sync::{CleanLockToken, RwLock},
syscall::{data::Stat, error::*, flag::*}, syscall::{data::Stat, error::*, flag::*},
}; };
+1 -1
View File
@@ -14,7 +14,7 @@ use syscall::EINTR;
use crate::{ use crate::{
context::{ context::{
self, self,
memory::{AccessMode, AddrSpace, AddrSpaceWrapper, Provider}, memory::{AccessMode, AddrSpace, Provider},
unblock_context, ContextLock, unblock_context, ContextLock,
}, },
memory::{Page, PhysicalAddress, VirtualAddress}, memory::{Page, PhysicalAddress, VirtualAddress},
+1 -2
View File
@@ -20,8 +20,7 @@ use crate::{
context::{self, context::FdTbl}, context::{self, context::FdTbl},
memory::{Page, VirtualAddress, PAGE_SIZE}, memory::{Page, VirtualAddress, PAGE_SIZE},
scheme::{ scheme::{
FileHandle, KernelScheme, SchemeExt, SchemeId, SchemeList, ALL_KERNEL_SCHEMES, FileHandle, KernelScheme, SchemeExt, SchemeList, ALL_KERNEL_SCHEMES, KERNEL_SCHEMES_COUNT,
KERNEL_SCHEMES_COUNT,
}, },
startup::Bootstrap, startup::Bootstrap,
syscall::{error::*, flag::MapFlags}, syscall::{error::*, flag::MapFlags},