Remove duplicated alarm syscall. (#636)

The alarm syscall is implemented in libtock-rs, but was duplicated here.
This removes the duplicated code and changes the references to point to
libtock-rs directly.

Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
This commit is contained in:
Zach Halvorsen
2023-07-11 08:42:50 -07:00
committed by GitHub
parent a274a512f7
commit 8868752e37
7 changed files with 31 additions and 121 deletions

View File

@@ -9,6 +9,7 @@ license = "MIT/Apache-2.0"
edition = "2018"
[dependencies]
libtock_alarm = { path = "../../third_party/libtock-rs/apis/alarm" }
libtock_console = { path = "../../third_party/libtock-rs/apis/console" }
libtock_platform = { path = "../../third_party/libtock-rs/platform" }

View File

@@ -8,105 +8,16 @@
//!
//! Adapted from the [libtock-rs](https://github.com/tock/libtock-rs/blob/master/apis/alarm/src/lib.rs) alarm driver interface
use crate::result::{FlexUnwrap, OtherError, TockError, TockResult};
use crate::util::Util;
use core::cell::Cell;
use crate::result::{OtherError, TockResult};
use core::marker::PhantomData;
use core::ops::{Add, AddAssign, Sub};
use libtock_alarm::{Hz, Alarm, Milliseconds, Convert};
use libtock_platform as platform;
use libtock_platform::{share, DefaultConfig, ErrorCode, Syscalls};
use libtock_platform::{DefaultConfig, ErrorCode, Syscalls};
use platform::share::Handle;
use platform::subscribe::OneId;
use platform::{Subscribe, Upcall};
pub struct Alarm<S: Syscalls, C: platform::subscribe::Config = DefaultConfig>(S, C);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Hz(pub u32);
pub trait Convert {
/// Converts a time unit by rounding up.
fn to_ticks(self, freq: Hz) -> Ticks;
}
#[derive(Copy, Clone, Debug)]
pub struct Ticks(pub u32);
impl Convert for Ticks {
fn to_ticks(self, _freq: Hz) -> Ticks {
self
}
}
pub fn get_ticks<S: Syscalls>() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::<u32, ErrorCode>()?)
}
pub fn get_clock_frequency<S: Syscalls>() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::FREQUENCY, 0, 0).to_result::<u32, ErrorCode>()?)
}
#[derive(Copy, Clone)]
pub struct Milliseconds(pub u32);
impl Convert for Milliseconds {
fn to_ticks(self, freq: Hz) -> Ticks {
// Saturating multiplication will top out at about 1 hour at 1MHz.
// It's large enough for an alarm, and much simpler than failing
// or losing precision for short sleeps.
/// u32::div_ceil is still unstable.
fn div_ceil(a: u32, other: u32) -> u32 {
let d = a / other;
let m = a % other;
if m == 0 {
d
} else {
d + 1
}
}
Ticks(div_ceil(self.0.saturating_mul(freq.0), 1000))
}
}
impl<S: Syscalls, C: platform::subscribe::Config> Alarm<S, C> {
/// Run a check against the console capsule to ensure it is present.
///
/// Returns number of concurrent notifications supported,
/// 0 if unbounded.
#[inline(always)]
pub fn driver_check() -> Result<u32, ErrorCode> {
S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).to_result()
}
pub fn get_frequency() -> Result<Hz, ErrorCode> {
S::command(DRIVER_NUM, command::FREQUENCY, 0, 0)
.to_result()
.map(Hz)
}
pub fn sleep_for<T: Convert>(time: T) -> Result<(), ErrorCode> {
let freq = Self::get_frequency()?;
let ticks = time.to_ticks(freq);
let called: Cell<Option<(u32, u32)>> = Cell::new(None);
share::scope(|subscribe| {
S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;
S::command(DRIVER_NUM, command::SET_RELATIVE, ticks.0, 0)
.to_result()
.map(|_when: u32| ())?;
loop {
S::yield_wait();
if let Some((_when, _ref)) = called.get() {
return Ok(());
}
}
})
}
}
pub struct Timer<S: Syscalls, C: platform::subscribe::Config = DefaultConfig> {
clock_frequency: Hz,
s: PhantomData<S>,
@@ -157,16 +68,13 @@ impl<S: Syscalls, C: platform::subscribe::Config, CB: Fn(ClockValue)>
S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).to_result::<(), ErrorCode>()?;
// Alarm driver only returns success as only a single concurrent timer is supported.
let clock_frequency =
S::command(DRIVER_NUM, command::FREQUENCY, 0, 0).to_result::<u32, ErrorCode>()?;
let clock_frequency = Alarm::<S>::get_frequency()?;
if clock_frequency < 1_000 {
if clock_frequency.0 < 1_000 {
// The alarm's frequency must be at least 1 kHz.
return Err(OtherError::TimerDriverErroneousClockFrequency.into());
}
let clock_frequency = Hz(clock_frequency);
Ok(Timer {
clock_frequency,
c: PhantomData,
@@ -202,19 +110,8 @@ impl<S: Syscalls, C: platform::subscribe::Config> Timer<S, C> {
}
}
pub fn sleep(duration: Duration<isize>) -> TockResult<()> {
let expired = Cell::new(false);
let mut with_callback = with_callback::<S, C, _>(|_| expired.set(true));
let mut timer = with_callback.init().flex_unwrap();
timer.set_alarm(duration).flex_unwrap();
Util::<S>::yieldk_for(|| expired.get());
match timer.stop_alarm() {
Ok(_) | Err(TockError::Command(ErrorCode::Already)) => Ok(()),
Err(e) => Err(e),
}
pub fn get_ticks() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::<u32, ErrorCode>()?)
}
/// Returns the clock frequency of the timer.
@@ -224,10 +121,8 @@ impl<S: Syscalls, C: platform::subscribe::Config> Timer<S, C> {
/// Returns the current counter tick value.
pub fn get_current_counter_ticks(&self) -> TockResult<ClockValue> {
let ticks = S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::<u32, ErrorCode>()?;
Ok(ClockValue {
num_ticks: ticks as isize,
num_ticks: Self::get_ticks()? as isize,
clock_frequency: self.clock_frequency(),
})
}