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
pub fn unblock_no_ipi(&mut self) -> bool {
if self.status.is_soft_blocked() {
+17 -29
View File
@@ -18,7 +18,7 @@ use crate::{
cpu_stats::CpuStatsData,
ipi::{ipi, IpiKind, IpiTarget},
memory::{RmmA, RmmArch, TableKind},
percpu::PercpuBlock,
percpu::{get_percpu_block, PercpuBlock},
sync::{
ArcRwLockWriteGuard, CleanLockToken, LockToken, Mutex, MutexGuard, RwLock, RwLockReadGuard,
RwLockWriteGuard, L0, L1, L2, L3, L4,
@@ -27,8 +27,6 @@ use crate::{
Ordering,
};
use crate::percpu::ALL_PERCPU_BLOCKS;
use self::context::Kstack;
pub use self::{
context::{BorrowedHtBuf, Context, Status},
@@ -144,21 +142,17 @@ pub fn wakeup_context(
let target_cpu = cpu_id.unwrap_or(curr_cpu);
if target_cpu != curr_cpu {
if let Some(percpu) = unsafe {
ALL_PERCPU_BLOCKS[target_cpu.get() as usize]
.load(Ordering::Acquire)
.as_ref()
} {
// non-local wakeup
percpu
.switch_internals
.ipi_context_wakeup_list
.lock(token.token())
.push(weak);
ipi(IpiKind::Wakeup, IpiTarget::Other);
return;
}
if target_cpu != curr_cpu
&& let Some(percpu) = get_percpu_block(target_cpu)
{
// non-local wakeup
percpu
.switch_internals
.ipi_context_wakeup_list
.lock(token.token())
.push(weak);
ipi(IpiKind::Wakeup, IpiTarget::Other);
return;
}
// local wakeup
@@ -393,17 +387,11 @@ pub fn get_contexts_stats(token: &mut CleanLockToken) -> [usize; 5] {
let mut switches = 0;
let mut syscall_switches = 0;
for i in 0..crate::cpu_count() {
if let Some(percpu) = unsafe {
ALL_PERCPU_BLOCKS[i as usize]
.load(Ordering::Acquire)
.as_ref()
} {
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;
}
for percpu in crate::percpu::all_percpu_blocks() {
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);
+3 -11
View File
@@ -9,7 +9,7 @@ use crate::{
},
cpu_set::LogicalCpuId,
cpu_stats::{self, CpuState},
percpu::{self, PercpuBlock, ALL_PERCPU_BLOCKS},
percpu::{self, get_percpu_block, PercpuBlock},
sync::{ArcRwLockWriteGuard, CleanLockToken, Mutex, L4},
};
use alloc::{
@@ -697,11 +697,7 @@ fn select_next_context(
continue;
}
if let Some(p) = unsafe {
ALL_PERCPU_BLOCKS[i as usize]
.load(Ordering::Acquire)
.as_ref()
} {
if let Some(p) = get_percpu_block(LogicalCpuId::new(i as u32)) {
let neighbour_len = p.switch_internals.queue_len.load(Ordering::Relaxed);
if neighbour_len > max_neighbour {
@@ -723,11 +719,7 @@ fn select_next_context(
if target_cpu == curr_cpu {
continue;
}
let Some(target_percpu) = (unsafe {
ALL_PERCPU_BLOCKS[target_cpu as usize]
.load(Ordering::Acquire)
.as_ref()
}) else {
let Some(target_percpu) = get_percpu_block(LogicalCpuId::new(target_cpu)) else {
continue;
};
+23 -29
View File
@@ -3,7 +3,7 @@ use core::{mem, ops::Add, ptr::write_bytes, slice};
use crate::{
acpi,
cpu_set::{LogicalCpuId, LogicalCpuSet, MAX_CPU_COUNT},
percpu::{self, ALL_PERCPU_BLOCKS},
percpu,
sync::{CleanLockToken, Mutex, L0},
};
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);
}
for cpu_ptr in percpu::ALL_PERCPU_BLOCKS.as_ref() {
if let Some(cpu) =
unsafe { cpu_ptr.load(core::sync::atomic::Ordering::Relaxed).as_mut() }
{
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
let cpu_id = cpu
.misc_arch_info
.apic_id_opt
.get()
.map(|e| e.get())
.unwrap();
for cpu in percpu::all_percpu_blocks() {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
let cpu_id = cpu
.misc_arch_info
.apic_id_opt
.get()
.map(|e| e.get())
.unwrap();
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
let cpu_id = 0; // TODO
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
let cpu_id = 0; // TODO
let n = numa_nodes
.iter()
.enumerate()
.find_map(|(i, node)| {
if node.cpus & 1u128 << cpu_id != 0 {
Some((i, node))
} else {
None
}
})
.map(|(i, node)| (i as u32, node));
cpu.numa_node.set(n);
} else {
break;
}
let n = numa_nodes
.iter()
.enumerate()
.find_map(|(i, node)| {
if node.cpus & 1u128 << cpu_id != 0 {
Some((i, node))
} else {
None
}
})
.map(|(i, node)| (i as u32, node));
cpu.numa_node.set(n);
}
NUMA_NODES.call_once(|| numa_nodes);
+16 -8
View File
@@ -25,6 +25,8 @@ use crate::{
};
/// 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 {
/// A unique immutable number that identifies the current CPU - used for scheduling
pub cpu_id: LogicalCpuId,
@@ -57,15 +59,25 @@ pub struct PercpuBlock {
pub static ALL_PERCPU_BLOCKS: [AtomicPtr<PercpuBlock>; 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)]
pub unsafe fn init_tlb_shootdown(id: LogicalCpuId, block: *mut PercpuBlock) {
ALL_PERCPU_BLOCKS[id.get() as usize].store(block, Ordering::Release)
}
pub fn get_all_stats() -> Vec<(LogicalCpuId, CpuStatsData)> {
let mut res = ALL_PERCPU_BLOCKS
.iter()
.filter_map(|block| unsafe { block.load(Ordering::Relaxed).as_ref() })
let mut res = (0..ALL_PERCPU_BLOCKS.len())
.filter_map(|i| get_percpu_block(LogicalCpuId::new(i as u32)))
.map(|block| {
let stats = &block.stats;
(block.cpu_id, stats.into())
@@ -86,11 +98,7 @@ pub fn shootdown_tlb_ipi(target: Option<LogicalCpuId>) {
let my_percpublock = PercpuBlock::current();
assert_ne!(target, my_percpublock.cpu_id);
let Some(percpublock) = (unsafe {
ALL_PERCPU_BLOCKS[target.get() as usize]
.load(Ordering::Acquire)
.as_ref()
}) else {
let Some(percpublock) = (get_percpu_block(target)) else {
warn!("Trying to TLB shootdown a CPU that doesn't exist or isn't initialized.");
return;
};
+1 -2
View File
@@ -23,11 +23,10 @@ use crate::{
GrantFileRef, MmapMode, PageSpan, UnmapVec, DANGLING,
},
unblock_context, wakeup_context, BorrowedHtBuf, ContextLock, PreemptGuard, PreemptGuardL1,
Status, WeakContextRef,
Status,
},
event,
memory::{Frame, Page, VirtualAddress, PAGE_SIZE},
percpu::PercpuBlock,
scheme::SchemeId,
sync::{CleanLockToken, LockToken, Mutex, RwLock, WaitQueue, L1},
syscall::{
+1 -1
View File
@@ -13,7 +13,7 @@ use crate::{
},
},
memory::{Page, VirtualAddress, PAGE_SIZE},
scheme::{self, FileHandle, KernelScheme, OpenResult, StrOrBytes},
scheme::{FileHandle, KernelScheme, OpenResult, StrOrBytes},
sync::{CleanLockToken, RwLock},
syscall::{data::Stat, error::*, flag::*},
};
+1 -1
View File
@@ -14,7 +14,7 @@ use syscall::EINTR;
use crate::{
context::{
self,
memory::{AccessMode, AddrSpace, AddrSpaceWrapper, Provider},
memory::{AccessMode, AddrSpace, Provider},
unblock_context, ContextLock,
},
memory::{Page, PhysicalAddress, VirtualAddress},
+1 -2
View File
@@ -20,8 +20,7 @@ use crate::{
context::{self, context::FdTbl},
memory::{Page, VirtualAddress, PAGE_SIZE},
scheme::{
FileHandle, KernelScheme, SchemeExt, SchemeId, SchemeList, ALL_KERNEL_SCHEMES,
KERNEL_SCHEMES_COUNT,
FileHandle, KernelScheme, SchemeExt, SchemeList, ALL_KERNEL_SCHEMES, KERNEL_SCHEMES_COUNT,
},
startup::Bootstrap,
syscall::{error::*, flag::MapFlags},