mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
Use RcuOption
for lazy-initialized soft-IRQ callbacks
This commit is contained in:
parent
a5065d878e
commit
78a695f21b
@ -225,14 +225,18 @@ macro_rules! define_timer_managers {
|
|||||||
fn _init_system_wide_timer_managers() {
|
fn _init_system_wide_timer_managers() {
|
||||||
$(
|
$(
|
||||||
let clock = paste! {[<$clock_id _INSTANCE>].get().unwrap().clone()};
|
let clock = paste! {[<$clock_id _INSTANCE>].get().unwrap().clone()};
|
||||||
let clock_manager = TimerManager::new(clock);
|
let timer_manager = TimerManager::new(clock);
|
||||||
for cpu in ostd::cpu::all_cpus() {
|
for cpu in ostd::cpu::all_cpus() {
|
||||||
paste! {
|
paste! {
|
||||||
[<$clock_id _MANAGER>].get_on_cpu(cpu).call_once(|| clock_manager.clone());
|
[<$clock_id _MANAGER>].get_on_cpu(cpu).call_once(|| timer_manager.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let callback = move || {
|
let callback = || {
|
||||||
clock_manager.process_expired_timers();
|
let preempt_guard = ostd::task::disable_preempt();
|
||||||
|
let cpu = preempt_guard.current_cpu();
|
||||||
|
paste! {
|
||||||
|
[<$clock_id _MANAGER>].get_on_cpu(cpu).get().unwrap().process_expired_timers();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
time::softirq::register_callback(callback);
|
time::softirq::register_callback(callback);
|
||||||
)*
|
)*
|
||||||
@ -267,10 +271,13 @@ pub static JIFFIES_TIMER_MANAGER: Once<Arc<TimerManager>> = Once::new();
|
|||||||
fn init_jiffies_clock_manager() {
|
fn init_jiffies_clock_manager() {
|
||||||
let jiffies_clock = JiffiesClock { _private: () };
|
let jiffies_clock = JiffiesClock { _private: () };
|
||||||
let jiffies_timer_manager = TimerManager::new(Arc::new(jiffies_clock));
|
let jiffies_timer_manager = TimerManager::new(Arc::new(jiffies_clock));
|
||||||
JIFFIES_TIMER_MANAGER.call_once(|| jiffies_timer_manager.clone());
|
JIFFIES_TIMER_MANAGER.call_once(|| jiffies_timer_manager);
|
||||||
|
|
||||||
let callback = move || {
|
let callback = || {
|
||||||
jiffies_timer_manager.process_expired_timers();
|
JIFFIES_TIMER_MANAGER
|
||||||
|
.get()
|
||||||
|
.unwrap()
|
||||||
|
.process_expired_timers();
|
||||||
};
|
};
|
||||||
time::softirq::register_callback(callback);
|
time::softirq::register_callback(callback);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec, vec::Vec};
|
||||||
|
|
||||||
use aster_softirq::{softirq_id::TIMER_SOFTIRQ_ID, SoftIrqLine};
|
use aster_softirq::{softirq_id::TIMER_SOFTIRQ_ID, SoftIrqLine};
|
||||||
use ostd::{
|
use ostd::{sync::RcuOption, timer};
|
||||||
sync::{LocalIrqDisabled, RwLock},
|
|
||||||
timer,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TIMER_SOFTIRQ_CALLBACKS: RwLock<Vec<Box<dyn Fn() + Sync + Send>>, LocalIrqDisabled> =
|
#[allow(clippy::type_complexity)]
|
||||||
RwLock::new(Vec::new());
|
#[allow(clippy::box_collection)]
|
||||||
|
static TIMER_SOFTIRQ_CALLBACKS: RcuOption<Box<Vec<fn()>>> = RcuOption::new_none();
|
||||||
|
|
||||||
pub(super) fn init() {
|
pub(super) fn init() {
|
||||||
SoftIrqLine::get(TIMER_SOFTIRQ_ID).enable(timer_softirq_handler);
|
SoftIrqLine::get(TIMER_SOFTIRQ_ID).enable(timer_softirq_handler);
|
||||||
@ -20,16 +18,41 @@ pub(super) fn init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a function that will be executed during timer softirq.
|
/// Registers a function that will be executed during timer softirq.
|
||||||
pub(super) fn register_callback<F>(func: F)
|
pub(super) fn register_callback(func: fn()) {
|
||||||
where
|
loop {
|
||||||
F: Fn() + Sync + Send + 'static,
|
let callbacks = TIMER_SOFTIRQ_CALLBACKS.read();
|
||||||
{
|
match callbacks.get() {
|
||||||
TIMER_SOFTIRQ_CALLBACKS.write().push(Box::new(func));
|
// Initialized, copy the vector, push the function and update.
|
||||||
|
Some(callbacks_vec) => {
|
||||||
|
let mut callbacks_cloned = callbacks_vec.clone();
|
||||||
|
callbacks_cloned.push(func);
|
||||||
|
if callbacks
|
||||||
|
.compare_exchange(Some(Box::new(callbacks_cloned)))
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Uninitialized, initialize it.
|
||||||
|
None => {
|
||||||
|
if callbacks
|
||||||
|
.compare_exchange(Some(Box::new(vec![func])))
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Contention on initialization or pushing, retry.
|
||||||
|
core::hint::spin_loop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timer_softirq_handler() {
|
fn timer_softirq_handler() {
|
||||||
let callbacks = TIMER_SOFTIRQ_CALLBACKS.read();
|
let callbacks = TIMER_SOFTIRQ_CALLBACKS.read();
|
||||||
for callback in callbacks.iter() {
|
if let Some(callbacks) = callbacks.get() {
|
||||||
(callback)();
|
for callback in callbacks.iter() {
|
||||||
|
(callback)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user