mirror of
https://github.com/redox-os/kernel.git
synced 2026-09-09 00:07:34 +08:00
Safe get-percpu wrapper and warnings fixes.
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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::*},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
Reference in New Issue
Block a user