From 466882e0b756791b89dfcd4e282ee5e44a910bd5 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Thu, 20 Nov 2025 14:09:21 +0100 Subject: [PATCH] WIP --- src/arch/aarch64/kernel/interrupts.rs | 7 +- src/arch/mod.rs | 2 + src/arch/riscv64/kernel/scheduler.rs | 8 +- src/arch/timer_interrupts.rs | 118 ++++++++++++++++++++++++++ src/arch/x86_64/kernel/scheduler.rs | 7 +- src/drivers/net/gem.rs | 4 + src/drivers/net/loopback.rs | 4 +- src/drivers/net/rtl8139.rs | 4 + src/drivers/net/virtio/mod.rs | 4 + src/executor/mod.rs | 96 ++------------------- src/executor/network.rs | 39 +++++++-- src/fd/socket/tcp.rs | 10 ++- src/fd/socket/udp.rs | 6 +- src/scheduler/mod.rs | 10 --- src/scheduler/task/mod.rs | 102 +++------------------- 15 files changed, 211 insertions(+), 210 deletions(-) create mode 100644 src/arch/timer_interrupts.rs diff --git a/src/arch/aarch64/kernel/interrupts.rs b/src/arch/aarch64/kernel/interrupts.rs index 97ad0d553c..c1efd2b944 100644 --- a/src/arch/aarch64/kernel/interrupts.rs +++ b/src/arch/aarch64/kernel/interrupts.rs @@ -17,6 +17,7 @@ use memory_addresses::arch::aarch64::PhysAddr; use crate::arch::aarch64::kernel::core_local::increment_irq_counter; use crate::arch::aarch64::kernel::scheduler::State; use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags}; +use crate::arch::timer_interrupts; #[cfg(not(feature = "pci"))] use crate::drivers::mmio::get_interrupt_handlers; #[cfg(feature = "pci")] @@ -93,10 +94,8 @@ pub(crate) fn install_handlers() { fn timer_handler() { debug!("Handle timer interrupt"); - - // disable timer - CNTP_CVAL_EL0.set(0); - CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::CLEAR); + timer_interrupts::clear_active(); + timer_interrupts::set_next_timer(); } for (key, value) in get_interrupt_handlers().into_iter() { diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 7a672be4e4..ac97fa0ca9 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -1,5 +1,7 @@ //! Architecture-specific architecture abstraction. +pub(crate) mod timer_interrupts; + cfg_if::cfg_if! { if #[cfg(target_arch = "aarch64")] { pub(crate) mod aarch64; diff --git a/src/arch/riscv64/kernel/scheduler.rs b/src/arch/riscv64/kernel/scheduler.rs index 9649083a3a..08fedb1e86 100644 --- a/src/arch/riscv64/kernel/scheduler.rs +++ b/src/arch/riscv64/kernel/scheduler.rs @@ -5,11 +5,10 @@ use free_list::{PageLayout, PageRange}; use memory_addresses::{PhysAddr, VirtAddr}; use crate::arch::riscv64::kernel::core_local::core_scheduler; -use crate::arch::riscv64::kernel::processor::set_oneshot_timer; use crate::arch::riscv64::mm::paging::{BasePageSize, PageSize, PageTableEntryFlags}; use crate::mm::{FrameAlloc, PageAlloc, PageRangeAllocator}; use crate::scheduler::task::{Task, TaskFrame}; -use crate::{DEFAULT_STACK_SIZE, KERNEL_STACK_SIZE}; +use crate::{DEFAULT_STACK_SIZE, KERNEL_STACK_SIZE, timer_interrupts}; #[repr(C, packed)] #[derive(Clone, Copy, Debug)] @@ -360,9 +359,10 @@ unsafe extern "C" fn task_start(func: extern "C" fn(usize), arg: usize, user_sta } pub fn timer_handler() { - //increment_irq_counter(apic::TIMER_INTERRUPT_NUMBER.into()); + debug!("Handle timer interrupt"); + timer_interrupts::clear_active(); + timer_interrupts::set_next_timer(); core_scheduler().handle_waiting_tasks(); - set_oneshot_timer(None); core_scheduler().scheduler(); } diff --git a/src/arch/timer_interrupts.rs b/src/arch/timer_interrupts.rs new file mode 100644 index 0000000000..45db3a17b4 --- /dev/null +++ b/src/arch/timer_interrupts.rs @@ -0,0 +1,118 @@ +use core::sync::atomic::{AtomicU64, Ordering}; + +#[cfg(feature = "net")] +use crate::executor::network::NETWORK_WAKER; +use crate::set_oneshot_timer; + +/// A possible timer interrupt source (i.e. reason the timer interrupt was set +/// up). +#[derive(PartialEq, Eq)] +pub enum Source { + Network, + Scheduler, +} + +/// A slot in the timer list. Each source is represented once. This is so that +/// we can have multiple timers at the same time with only one hardware timer. +struct Slot { + /// Timer source. + source: Source, + /// Point in time at which to wake up (in microsecond precision). + /// A value of [`u64::MAX`] means the timer is not set. + wakeup_time: AtomicU64, +} + +/// The actual timer list with one entry for each source. +static TIMERS: [Slot; 2] = [ + Slot { + source: Source::Network, + wakeup_time: AtomicU64::new(u64::MAX), + }, + Slot { + source: Source::Scheduler, + wakeup_time: AtomicU64::new(u64::MAX), + }, +]; + +/// Create a new timer, overriding any previous timer for the source. +#[cfg(feature = "net")] +pub fn create_timer(source: Source, wakeup_micros: u64) { + trace!("Setting relative timer interrupt for {wakeup_micros}us"); + + create_timer_abs( + source, + crate::arch::processor::get_timer_ticks() + wakeup_micros, + ); +} + +/// Crete a new timer, but with an absolute wakeup time. +pub fn create_timer_abs(source: Source, wakeup_time: u64) { + trace!( + "Setting an absolute timer interrupt for {}us", + wakeup_time - crate::arch::processor::get_timer_ticks() + ); + + { + // SAFETY: Our timer list has an entry for every possible source + let previous_entry = TIMERS.iter().find(|slot| slot.source == source).unwrap(); + + // Overwrite the wakeup time + previous_entry + .wakeup_time + .store(wakeup_time, Ordering::Relaxed); + } + + // If this timer is the one closest in the future, set the real timer to it + // SAFETY: There's more than 1 slot + if TIMERS + .iter() + .map(|slot| slot.wakeup_time.load(Ordering::Relaxed)) + .min_by(|a, b| a.cmp(b)) + .unwrap() + == wakeup_time + { + trace!("Setting the oneshot timer now"); + + set_oneshot_timer(Some(wakeup_time)); + } +} + +/// Sets the next timer or disables it if no timer is pending. +pub fn set_next_timer() { + // SAFETY: There's more than 1 slot + let lowest_timer = TIMERS + .iter() + .map(|slot| slot.wakeup_time.load(Ordering::Relaxed)) + .min_by(|a, b| a.cmp(b)) + .unwrap(); + + if lowest_timer == u64::MAX { + set_oneshot_timer(None); + } else { + set_oneshot_timer(Some(lowest_timer)); + } +} + +/// Clears the timer slot for the currently active timer. +pub fn clear_active() { + // SAFETY: There's more than 1 slot + let lowest_timer = TIMERS + .iter() + .min_by(|a, b| { + a.wakeup_time + .load(Ordering::Relaxed) + .cmp(&b.wakeup_time.load(Ordering::Relaxed)) + }) + .unwrap(); + + // TODO: Do we really want to do this here? + match lowest_timer.source { + #[cfg(feature = "net")] + Source::Network => NETWORK_WAKER.lock().wake(), + _ => {} // no-op, we always poll after a timer interrupt + } + + trace!("Cleared active timer"); + + lowest_timer.wakeup_time.store(u64::MAX, Ordering::Relaxed); +} diff --git a/src/arch/x86_64/kernel/scheduler.rs b/src/arch/x86_64/kernel/scheduler.rs index e60f86c1ff..22fd119f49 100644 --- a/src/arch/x86_64/kernel/scheduler.rs +++ b/src/arch/x86_64/kernel/scheduler.rs @@ -14,10 +14,10 @@ use crate::arch::x86_64::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; use crate::config::*; -use crate::env; use crate::mm::{FrameAlloc, PageAlloc, PageRangeAllocator}; use crate::scheduler::PerCoreSchedulerExt; use crate::scheduler::task::{Task, TaskFrame}; +use crate::{env, timer_interrupts}; #[repr(C, packed)] struct State { @@ -318,6 +318,11 @@ impl TaskFrame for Task { extern "x86-interrupt" fn timer_handler(_stack_frame: interrupts::ExceptionStackFrame) { increment_irq_counter(apic::TIMER_INTERRUPT_NUMBER); + + debug!("Handle timer interrupt"); + timer_interrupts::clear_active(); + timer_interrupts::set_next_timer(); + core_scheduler().handle_waiting_tasks(); apic::eoi(); core_scheduler().reschedule(); diff --git a/src/drivers/net/gem.rs b/src/drivers/net/gem.rs index a619721ccc..4b39d5723a 100644 --- a/src/drivers/net/gem.rs +++ b/src/drivers/net/gem.rs @@ -32,6 +32,7 @@ use crate::drivers::net::{NetworkDriver, mtu}; #[cfg(feature = "pci")] use crate::drivers::pci as hardware; use crate::drivers::{Driver, InterruptLine}; +use crate::executor::network::NETWORK_WAKER; use crate::mm::device_alloc::DeviceAlloc; use crate::{BasePageSize, PageSize}; @@ -276,6 +277,9 @@ impl NetworkDriver for GEMDriver { fn handle_interrupt(&mut self) { self.tx_fields.handle_interrupt(); + + trace!("Waking network waker"); + NETWORK_WAKER.lock().wake(); } } diff --git a/src/drivers/net/loopback.rs b/src/drivers/net/loopback.rs index 9a2ab1be67..fe7ae3f348 100644 --- a/src/drivers/net/loopback.rs +++ b/src/drivers/net/loopback.rs @@ -8,6 +8,7 @@ use smoltcp::time::Instant; use crate::drivers::net::NetworkDriver; use crate::drivers::{Driver, InterruptLine}; +use crate::executor::network::NETWORK_WAKER; use crate::mm::device_alloc::DeviceAlloc; pub(crate) struct LoopbackDriver { @@ -122,7 +123,8 @@ impl NetworkDriver for LoopbackDriver { } fn handle_interrupt(&mut self) { - // no-op + trace!("Waking network waker"); + NETWORK_WAKER.lock().wake(); } } diff --git a/src/drivers/net/rtl8139.rs b/src/drivers/net/rtl8139.rs index c75e4cbdeb..fca1ba4e14 100644 --- a/src/drivers/net/rtl8139.rs +++ b/src/drivers/net/rtl8139.rs @@ -21,6 +21,7 @@ use crate::drivers::Driver; use crate::drivers::error::DriverError; use crate::drivers::net::{NetworkDriver, mtu}; use crate::drivers::pci::PciDevice; +use crate::executor::network::NETWORK_WAKER; use crate::mm::device_alloc::DeviceAlloc; /// size of the receive buffer @@ -687,6 +688,9 @@ impl NetworkDriver for RTL8139Driver { self.regs.as_mut_ptr().isr().write(le16::from( isr_contents & (ISR_RXOVW | ISR_TER | ISR_RER | ISR_TOK | ISR_ROK), )); + + trace!("Waking network waker"); + NETWORK_WAKER.lock().wake(); } } diff --git a/src/drivers/net/virtio/mod.rs b/src/drivers/net/virtio/mod.rs index 334b6eed23..45c59cac1a 100644 --- a/src/drivers/net/virtio/mod.rs +++ b/src/drivers/net/virtio/mod.rs @@ -41,6 +41,7 @@ use crate::drivers::virtio::virtqueue::{ AvailBufferToken, BufferElem, BufferType, UsedBufferToken, VirtQueue, Virtq, }; use crate::drivers::{Driver, InterruptLine}; +use crate::executor::network::NETWORK_WAKER; use crate::mm::device_alloc::DeviceAlloc; /// A wrapper struct for the raw configuration structure. @@ -416,6 +417,9 @@ impl NetworkDriver for VirtioNetDriver { } self.isr_stat.acknowledge(); + + trace!("Waking network waker"); + NETWORK_WAKER.lock().wake(); } } diff --git a/src/executor/mod.rs b/src/executor/mod.rs index cc65b85aa6..cb5f903219 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -18,15 +18,11 @@ use core::time::Duration; use crossbeam_utils::Backoff; use hermit_sync::without_interrupts; -#[cfg(feature = "net")] -use smoltcp::time::Instant; use crate::arch::core_local; use crate::errno::Errno; use crate::executor::task::AsyncTask; use crate::io; -#[cfg(feature = "net")] -use crate::scheduler::PerCoreSchedulerExt; use crate::synch::futex::*; /// WakerRegistration is derived from smoltcp's @@ -155,101 +151,27 @@ where let now = crate::arch::kernel::systemtime::now_micros(); if let Poll::Ready(t) = result { - // allow network interrupts - #[cfg(feature = "net")] - { - if let Some(mut guard) = crate::executor::network::NIC.try_lock() { - let delay = if let Ok(nic) = guard.as_nic_mut() { - nic.set_polling_mode(false); - - nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap())) - .map(|d| d.total_micros()) - } else { - None - }; - core_local::core_scheduler().add_network_timer( - delay.map(|d| crate::arch::processor::get_timer_ticks() + d), - ); - } - } - return t; } if let Some(duration) = timeout && Duration::from_micros(now - start) >= duration { - // allow network interrupts - #[cfg(feature = "net")] - { - if let Some(mut guard) = crate::executor::network::NIC.try_lock() { - let delay = if let Ok(nic) = guard.as_nic_mut() { - nic.set_polling_mode(false); - - nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap())) - .map(|d| d.total_micros()) - } else { - None - }; - core_local::core_scheduler().add_network_timer( - delay.map(|d| crate::arch::processor::get_timer_ticks() + d), - ); - } - } - return Err(Errno::Time); } - #[cfg(feature = "net")] + // TODO: I have no idea whether this is correct if backoff.is_completed() { - let delay = if let Some(mut guard) = crate::executor::network::NIC.try_lock() { - if let Ok(nic) = guard.as_nic_mut() { - nic.set_polling_mode(false); - - nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap())) - .map(|d| d.total_micros()) - } else { - None - } - } else { - None - }; - - if delay.unwrap_or(10_000_000) > 10_000 { - core_local::core_scheduler().add_network_timer( - delay.map(|d| crate::arch::processor::get_timer_ticks() + d), - ); - let wakeup_time = - timeout.map(|duration| start + u64::try_from(duration.as_micros()).unwrap()); - - // switch to another task - task_notify.wait(wakeup_time); - - // restore default values - if let Ok(nic) = crate::executor::network::NIC.lock().as_nic_mut() { - nic.set_polling_mode(true); - } - - backoff.reset(); - } - } else { - backoff.snooze(); - } - - #[cfg(not(feature = "net"))] - { - if backoff.is_completed() { - let wakeup_time = - timeout.map(|duration| start + u64::try_from(duration.as_micros()).unwrap()); + let wakeup_time = + timeout.map(|duration| start + u64::try_from(duration.as_micros()).unwrap()); - // switch to another task - task_notify.wait(wakeup_time); + // switch to another task + task_notify.wait(wakeup_time); - // restore default values - backoff.reset(); - } else { - backoff.snooze(); - } + // restore default values + backoff.reset(); + } else { + backoff.snooze(); } } } diff --git a/src/executor/network.rs b/src/executor/network.rs index 3fc25abcb1..c0de8d5ea3 100644 --- a/src/executor/network.rs +++ b/src/executor/network.rs @@ -26,10 +26,10 @@ use crate::arch; use crate::drivers::net::{NetworkDevice, NetworkDriver}; #[cfg(feature = "dns")] use crate::errno::Errno; -use crate::executor::spawn; +use crate::executor::{WakerRegistration, spawn}; #[cfg(feature = "dns")] use crate::io; -use crate::scheduler::PerCoreSchedulerExt; +use crate::timer_interrupts::{Source, create_timer}; pub(crate) enum NetworkState<'a> { Missing, @@ -189,14 +189,35 @@ async fn dhcpv4_run() { .await; } +pub(crate) static NETWORK_WAKER: InterruptTicketMutex = + InterruptTicketMutex::new(WakerRegistration::new()); + async fn network_run() { future::poll_fn(|cx| { if let Some(mut guard) = NIC.try_lock() { match &mut *guard { NetworkState::Initialized(nic) => { - nic.poll_common(now()); - // FIXME: only wake when progress can be made - cx.waker().wake_by_ref(); + let now = now(); + + // TODO: smoltcp is probably not exposing enough information here + // Well, how could it! Impossible :) + match nic.poll_common(now) { + PollResult::SocketStateChanged => { + // Progress was made + cx.waker().wake_by_ref(); + } + PollResult::None => { + // Very likely no progress can be made, so set up a timer interrupt to wake the waker + NETWORK_WAKER.lock().register(cx.waker()); + nic.set_polling_mode(false); + if let Some(wakeup_time) = nic.poll_delay(now).map(|d| d.total_micros()) + { + create_timer(Source::Network, wakeup_time); + trace!("Configured an interrupt for {wakeup_time:?}"); + } + } + } + Poll::Pending } _ => Poll::Ready(()), @@ -255,12 +276,12 @@ pub(crate) fn init() { *guard = NetworkInterface::create(); if let NetworkState::Initialized(nic) = &mut *guard { + // TODO: Is this really necessary? let time = now(); nic.poll_common(time); - let wakeup_time = nic - .poll_delay(time) - .map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros()); - crate::core_scheduler().add_network_timer(wakeup_time); + if let Some(wakeup_time) = nic.poll_delay(time).map(|d| d.total_micros()) { + create_timer(Source::Network, wakeup_time); + } spawn(network_run()); #[cfg(feature = "dhcpv4")] diff --git a/src/fd/socket/tcp.rs b/src/fd/socket/tcp.rs index a696adb20d..59a2110b92 100644 --- a/src/fd/socket/tcp.rs +++ b/src/fd/socket/tcp.rs @@ -13,7 +13,7 @@ use smoltcp::wire::{IpEndpoint, Ipv4Address, Ipv6Address}; use crate::errno::Errno; use crate::executor::block_on; -use crate::executor::network::{Handle, NIC}; +use crate::executor::network::{Handle, NETWORK_WAKER, NIC}; use crate::fd::{self, Endpoint, ListenEndpoint, ObjectInterface, PollEvent, SocketOption}; use crate::syscalls::socket::Af; use crate::{DEFAULT_KEEP_ALIVE_INTERVAL, io}; @@ -64,14 +64,18 @@ impl Socket { fn with(&self, f: impl FnOnce(&mut tcp::Socket<'_>) -> R) -> R { let mut guard = NIC.lock(); let nic = guard.as_nic_mut().unwrap(); - f(nic.get_mut_socket::>(*self.handle.first().unwrap())) + let r = f(nic.get_mut_socket::>(*self.handle.first().unwrap())); + NETWORK_WAKER.lock().wake(); + r } fn with_context(&self, f: impl FnOnce(&mut tcp::Socket<'_>, &mut iface::Context) -> R) -> R { let mut guard = NIC.lock(); let nic = guard.as_nic_mut().unwrap(); let (s, cx) = nic.get_socket_and_context::>(*self.handle.first().unwrap()); - f(s, cx) + let r = f(s, cx); + NETWORK_WAKER.lock().wake(); + r } async fn close(&self) -> io::Result<()> { diff --git a/src/fd/socket/udp.rs b/src/fd/socket/udp.rs index 8db1a6780c..09cf56a300 100644 --- a/src/fd/socket/udp.rs +++ b/src/fd/socket/udp.rs @@ -10,7 +10,7 @@ use smoltcp::wire::{IpEndpoint, Ipv4Address, Ipv6Address}; use crate::errno::Errno; use crate::executor::block_on; -use crate::executor::network::{Handle, NIC}; +use crate::executor::network::{Handle, NETWORK_WAKER, NIC}; use crate::fd::{self, Endpoint, ListenEndpoint, ObjectInterface, PollEvent}; use crate::io; use crate::syscalls::socket::Af; @@ -43,7 +43,9 @@ impl Socket { fn with(&self, f: impl FnOnce(&mut udp::Socket<'_>) -> R) -> R { let mut guard = NIC.lock(); let nic = guard.as_nic_mut().unwrap(); - f(nic.get_mut_socket::>(self.handle)) + let r = f(nic.get_mut_socket::>(self.handle)); + NETWORK_WAKER.lock().wake(); + r } async fn close(&self) -> io::Result<()> { diff --git a/src/scheduler/mod.rs b/src/scheduler/mod.rs index 0d65303071..574a22bc8a 100644 --- a/src/scheduler/mod.rs +++ b/src/scheduler/mod.rs @@ -97,9 +97,6 @@ pub(crate) trait PerCoreSchedulerExt { /// Interrupt flag will be cleared during the reschedule fn reschedule(self); - #[cfg(feature = "net")] - fn add_network_timer(self, wakeup_time: Option); - /// Terminate the current task on the current core. fn exit(self, exit_code: i32) -> !; } @@ -170,13 +167,6 @@ impl PerCoreSchedulerExt for &mut PerCoreScheduler { without_interrupts(|| self.scheduler()); } - #[cfg(feature = "net")] - fn add_network_timer(self, wakeup_time: Option) { - without_interrupts(|| { - self.blocked_tasks.add_network_timer(wakeup_time); - }); - } - fn exit(self, exit_code: i32) -> ! { without_interrupts(|| { // Get the current task. diff --git a/src/scheduler/task/mod.rs b/src/scheduler/task/mod.rs index e91e5306de..bfeb5c7a58 100644 --- a/src/scheduler/task/mod.rs +++ b/src/scheduler/task/mod.rs @@ -23,6 +23,7 @@ use crate::arch::scheduler::TaskStacks; use crate::fd::stdio::*; use crate::fd::{FileDescriptor, ObjectInterface, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; use crate::scheduler::CoreId; +use crate::timer_interrupts::{Source, create_timer_abs}; use crate::{arch, env}; /// Returns the most significant bit. @@ -523,16 +524,12 @@ impl BlockedTask { pub(crate) struct BlockedTaskQueue { list: LinkedList, - #[cfg(feature = "net")] - network_wakeup_time: Option, } impl BlockedTaskQueue { pub const fn new() -> Self { Self { list: LinkedList::new(), - #[cfg(feature = "net")] - network_wakeup_time: None, } } @@ -559,20 +556,6 @@ impl BlockedTaskQueue { borrowed.status = TaskStatus::Ready; } - #[cfg(feature = "net")] - pub fn add_network_timer(&mut self, wakeup_time: Option) { - self.network_wakeup_time = wakeup_time; - - let next = self.list.front().and_then(|t| t.wakeup_time); - - let time = match (wakeup_time, next) { - (Some(a), Some(b)) => Some(a.min(b)), - (a, b) => a.or(b), - }; - - arch::set_oneshot_timer(time); - } - /// Blocks the given task for `wakeup_time` ticks, or indefinitely if None is given. pub fn add(&mut self, task: Rc>, wakeup_time: Option) { { @@ -594,35 +577,20 @@ impl BlockedTaskQueue { // Shall the task automatically be woken up after a certain time? if let Some(wt) = wakeup_time { let mut cursor = self.list.cursor_front_mut(); - let set_oneshot_timer = || { - #[cfg(not(feature = "net"))] - arch::set_oneshot_timer(wakeup_time); - #[cfg(feature = "net")] - match self.network_wakeup_time { - Some(time) => { - if time > wt { - arch::set_oneshot_timer(wakeup_time); - } else { - arch::set_oneshot_timer(self.network_wakeup_time); - } - } - _ => arch::set_oneshot_timer(wakeup_time), - } - }; while let Some(node) = cursor.current() { let node_wakeup_time = node.wakeup_time; if node_wakeup_time.is_none() || wt < node_wakeup_time.unwrap() { cursor.insert_before(new_node); - set_oneshot_timer(); + create_timer_abs(Source::Scheduler, wt); return; } cursor.move_next(); } - set_oneshot_timer(); + create_timer_abs(Source::Scheduler, wt); } self.list.push_back(new_node); @@ -633,13 +601,6 @@ impl BlockedTaskQueue { let mut first_task = true; let mut cursor = self.list.cursor_front_mut(); - #[cfg(feature = "net")] - if let Some(wakeup_time) = self.network_wakeup_time - && wakeup_time <= arch::processor::get_timer_ticks() - { - self.network_wakeup_time = None; - } - // Loop through all blocked tasks to find it. while let Some(node) = cursor.current() { if node.task.borrow().id == task.get_id() { @@ -649,29 +610,12 @@ impl BlockedTaskQueue { // If this is the first task, adjust the One-Shot Timer to fire at the // next task's wakeup time (if any). - #[cfg(feature = "net")] - if first_task { - arch::set_oneshot_timer(cursor.current().map_or_else( - || self.network_wakeup_time, - |node| match node.wakeup_time { - Some(wt) => { - if let Some(timer) = self.network_wakeup_time { - if wt < timer { Some(wt) } else { Some(timer) } - } else { - Some(wt) - } - } - None => self.network_wakeup_time, - }, - )); - } - #[cfg(not(feature = "net"))] - if first_task { - arch::set_oneshot_timer( - cursor - .current() - .map_or_else(|| None, |node| node.wakeup_time), - ); + if first_task + && let Some(wakeup) = cursor + .current() + .map_or_else(|| None, |node| node.wakeup_time) + { + create_timer_abs(Source::Scheduler, wakeup); } // Wake it up. @@ -695,15 +639,6 @@ impl BlockedTaskQueue { // Get the current time. let time = arch::processor::get_timer_ticks(); - #[cfg(feature = "net")] - if let Some(mut guard) = crate::executor::network::NIC.try_lock() - && let crate::executor::network::NetworkState::Initialized(nic) = &mut *guard - { - let now = crate::executor::network::now(); - nic.poll_common(now); - self.network_wakeup_time = nic.poll_delay(now).map(|d| d.total_micros() + time); - } - // Get the wakeup time of this task and check if we have reached the first task // that hasn't elapsed yet or waits indefinitely. // This iterator has to be consumed to actually remove the elements. @@ -719,20 +654,9 @@ impl BlockedTaskQueue { } let new_task_wakeup_time = self.list.front().and_then(|task| task.wakeup_time); - cfg_if::cfg_if! { - if #[cfg(feature = "net")] { - let network_wakeup_time = self.network_wakeup_time; - } else { - let network_wakeup_time = None; - } - }; - let timer_wakeup_time = match (new_task_wakeup_time, network_wakeup_time) { - (None, None) => None, - (None, Some(network_wt)) => Some(network_wt), - (Some(task_wt), None) => Some(task_wt), - (Some(task_wt), Some(network_wt)) => Some(u64::min(task_wt, network_wt)), - }; - - arch::set_oneshot_timer(timer_wakeup_time); + + if let Some(wakeup) = new_task_wakeup_time { + create_timer_abs(Source::Scheduler, wakeup); + } } }