Skip to content

Commit

Permalink
new interface to network driver
Browse files Browse the repository at this point in the history
the new interface is required for hermit-os/hermit-rs#117
  • Loading branch information
stlankes committed May 26, 2021
1 parent d99592e commit 5dafde0
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 95 deletions.
88 changes: 5 additions & 83 deletions src/drivers/net/mod.rs
Expand Up @@ -16,10 +16,7 @@ use crate::arch::kernel::irq::ExceptionStackFrame;
#[cfg(feature = "pci")]
use crate::arch::kernel::pci;
use crate::arch::kernel::percore::*;
use crate::scheduler::task::TaskHandle;
use crate::synch::semaphore::*;
use crate::synch::spinlock::SpinlockIrqSave;
use alloc::collections::BTreeMap;
use core::sync::atomic::{AtomicBool, Ordering};

/// A trait for accessing the network interface
Expand All @@ -45,100 +42,25 @@ pub trait NetworkInterface {
}

static NET_SEM: Semaphore = Semaphore::new(0);
static NIC_QUEUE: SpinlockIrqSave<BTreeMap<usize, TaskHandle>> =
SpinlockIrqSave::new(BTreeMap::new());
static POLLING: AtomicBool = AtomicBool::new(false);

/// period (in usec) to check, if the driver should still use the polling mode
const POLL_PERIOD: u64 = 20_000;

/// set driver in polling mode and threads will not be blocked
fn set_polling_mode(value: bool) {
pub fn set_polling_mode(value: bool) {
// is the driver already in polling mode?
if POLLING.swap(value, Ordering::SeqCst) != value {
#[cfg(feature = "pci")]
if let Some(driver) = crate::arch::kernel::pci::get_network_driver() {
driver.lock().set_polling_mode(value)
}

// wakeup network thread to sleep for longer time
NET_SEM.release();
}
}

pub fn netwakeup() {
NET_SEM.release();
pub fn netwait() {
NET_SEM.acquire(None);
}

pub fn netwait_and_wakeup(handles: &[usize], millis: Option<u64>) {
// do we have to wakeup a thread?
if handles.len() > 0 {
let mut guard = NIC_QUEUE.lock();

for i in handles {
if let Some(task) = guard.remove(i) {
core_scheduler().custom_wakeup(task);
}
}
}

let mut reset_nic = false;

// check if the driver should be in the polling mode
while POLLING.swap(false, Ordering::SeqCst) == true {
reset_nic = true;

let core_scheduler = core_scheduler();
let wakeup_time = Some(crate::arch::processor::get_timer_ticks() + POLL_PERIOD);

core_scheduler.block_current_task(wakeup_time);

// Switch to the next task.
core_scheduler.reschedule();
}

if reset_nic {
#[cfg(feature = "pci")]
if let Some(driver) = crate::arch::kernel::pci::get_network_driver() {
driver.lock().set_polling_mode(false);
};
} else {
NET_SEM.acquire(millis);
}
}

pub fn netwait(handle: usize, millis: Option<u64>) {
// smoltcp want to poll the nic
let is_polling = if let Some(t) = millis { t == 0 } else { false };

if is_polling {
set_polling_mode(true);
} else {
let wakeup_time = match millis {
Some(ms) => Some(crate::arch::processor::get_timer_ticks() + ms * 1000),
_ => None,
};
let mut guard = NIC_QUEUE.lock();
let core_scheduler = core_scheduler();

// Block the current task and add it to the wakeup queue.
core_scheduler.block_current_task(wakeup_time);
guard.insert(handle, core_scheduler.get_current_task_handle());

// release lock
drop(guard);

// Switch to the next task.
core_scheduler.reschedule();

// if the timer is expired, we have still the task in the btreemap
// => remove it from the btreemap
if millis.is_some() {
let mut guard = NIC_QUEUE.lock();

guard.remove(&handle);
}
}
pub fn netwakeup() {
NET_SEM.release();
}

#[cfg(target_arch = "x86_64")]
Expand Down
13 changes: 4 additions & 9 deletions src/syscalls/mod.rs
Expand Up @@ -142,21 +142,16 @@ pub fn sys_rx_buffer_consumed(handle: usize) -> Result<(), ()> {
kernel_function!(__sys_rx_buffer_consumed(handle))
}

#[cfg(not(feature = "newlib"))]
fn __sys_netwait(handle: usize, millis: Option<u64>) {
netwait(handle, millis)
}

#[cfg(not(feature = "newlib"))]
#[no_mangle]
pub fn sys_netwait(handle: usize, millis: Option<u64>) {
kernel_function!(__sys_netwait(handle, millis));
pub extern "C" fn sys_netwait() {
kernel_function!(netwait());
}

#[cfg(not(feature = "newlib"))]
#[no_mangle]
pub fn sys_netwait_and_wakeup(handles: &[usize], millis: Option<u64>) {
kernel_function!(netwait_and_wakeup(handles, millis));
pub extern "C" fn sys_set_network_polling_mode(value: bool) {
kernel_function!(set_polling_mode(value));
}

pub fn __sys_shutdown(arg: i32) -> ! {
Expand Down
12 changes: 9 additions & 3 deletions src/syscalls/tasks.rs
Expand Up @@ -289,19 +289,25 @@ pub extern "C" fn sys_join(id: Tid) -> i32 {
/// Mapping between TaskID and TaskHandle
static TASKS: SpinlockIrqSave<BTreeMap<TaskId, TaskHandle>> = SpinlockIrqSave::new(BTreeMap::new());

fn __sys_block_current_task() {
fn __sys_block_current_task(timeout: Option<u64>) {
let core_scheduler = core_scheduler();
let handle = core_scheduler.get_current_task_handle();
let tid = core_scheduler.get_current_task_id();

TASKS.lock().insert(tid, handle);
core_scheduler.block_current_task(None);
core_scheduler.block_current_task(timeout);
}

/// Set the current task state to `blocked`
#[no_mangle]
pub extern "C" fn sys_block_current_task() {
kernel_function!(__sys_block_current_task())
kernel_function!(__sys_block_current_task(None))
}

/// Set the current task state to `blocked`
#[no_mangle]
pub fn sys_block_current_task_with_timeout(timeout: Option<u64>) {
kernel_function!(__sys_block_current_task(timeout))
}

fn __sys_wakeup_task(id: Tid) {
Expand Down

0 comments on commit 5dafde0

Please sign in to comment.