From c1f89f0b36758820cdf8fc40ee951592da890985 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 20 Oct 2024 15:38:10 +0200 Subject: [PATCH 1/7] Move CMOS and RTC to clk module --- src/sys/{ => clk}/cmos.rs | 97 +------------------------------------- src/sys/clk/mod.rs | 7 +++ src/sys/clk/rtc.rs | 99 +++++++++++++++++++++++++++++++++++++++ src/sys/clock.rs | 2 +- src/sys/fs/device.rs | 2 +- src/sys/mod.rs | 2 +- src/sys/time.rs | 2 +- 7 files changed, 111 insertions(+), 100 deletions(-) rename src/sys/{ => clk}/cmos.rs (71%) create mode 100644 src/sys/clk/mod.rs create mode 100644 src/sys/clk/rtc.rs diff --git a/src/sys/cmos.rs b/src/sys/clk/cmos.rs similarity index 71% rename from src/sys/cmos.rs rename to src/sys/clk/cmos.rs index 99fe704b..fcd5d551 100644 --- a/src/sys/cmos.rs +++ b/src/sys/clk/cmos.rs @@ -1,105 +1,10 @@ -use crate::sys; -use crate::api::clock::{DATE_TIME, DATE_TIME_LEN}; -use crate::api::fs::{FileIO, IO}; +use super::{Interrupt, RTC, Register, RTC_CENTURY}; -use alloc::string::String; use bit_field::BitField; use core::hint::spin_loop; -use time::{Date, PrimitiveDateTime}; use x86_64::instructions::interrupts; use x86_64::instructions::port::Port; -const RTC_CENTURY: u16 = 2000; // NOTE: Change this at the end of 2099 - -#[repr(u8)] -enum Register { - Second = 0x00, - Minute = 0x02, - Hour = 0x04, - Day = 0x07, - Month = 0x08, - Year = 0x09, - A = 0x0A, - B = 0x0B, - C = 0x0C, -} - -#[repr(u8)] -enum Interrupt { - Periodic = 1 << 6, - Alarm = 1 << 5, - Update = 1 << 4, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct RTC { - pub year: u16, - pub month: u8, - pub day: u8, - pub hour: u8, - pub minute: u8, - pub second: u8, -} - -impl RTC { - pub fn new() -> Self { - CMOS::new().rtc() - } - - pub fn size() -> usize { - DATE_TIME_LEN - } - - pub fn sync(&mut self) { - *self = RTC::new(); - } -} - -impl FileIO for RTC { - fn read(&mut self, buf: &mut [u8]) -> Result { - self.sync(); - let date = Date::try_from_ymd( - self.year.into(), self.month, self.day - ).map_err(|_| ())?; - let date_time = date.try_with_hms( - self.hour, self.minute, self.second - ).map_err(|_| ())?; - let out = date_time.format(DATE_TIME); - buf.copy_from_slice(out.as_bytes()); - Ok(out.len()) - } - - fn write(&mut self, buf: &[u8]) -> Result { - let s = String::from_utf8_lossy(buf); - let s = s.trim_end(); - if s.len() != RTC::size() { - return Err(()); - } - let date_time = PrimitiveDateTime::parse(s, DATE_TIME).map_err(|_| ())?; - self.year = date_time.year() as u16; - self.month = date_time.month(); - self.day = date_time.day(); - self.hour = date_time.hour(); - self.minute = date_time.minute(); - self.second = date_time.second(); - if self.year < RTC_CENTURY || self.year > RTC_CENTURY + 99 { - return Err(()); - } - CMOS::new().update_rtc(self); - sys::clock::init(); - Ok(buf.len()) - } - - fn close(&mut self) {} - - fn poll(&mut self, event: IO) -> bool { - match event { - IO::Read => true, - IO::Write => true, - } - } -} - pub struct CMOS { addr: Port, data: Port, diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs new file mode 100644 index 00000000..98624191 --- /dev/null +++ b/src/sys/clk/mod.rs @@ -0,0 +1,7 @@ +mod cmos; +mod rtc; + +pub use cmos::CMOS; +pub use rtc::RTC; + +use rtc::{Interrupt, Register, RTC_CENTURY}; diff --git a/src/sys/clk/rtc.rs b/src/sys/clk/rtc.rs new file mode 100644 index 00000000..a8943f60 --- /dev/null +++ b/src/sys/clk/rtc.rs @@ -0,0 +1,99 @@ +use super::CMOS; + +use crate::sys; +use crate::api::clock::{DATE_TIME, DATE_TIME_LEN}; +use crate::api::fs::{FileIO, IO}; + +use alloc::string::String; +use time::{Date, PrimitiveDateTime}; + +pub const RTC_CENTURY: u16 = 2000; // NOTE: Change this at the end of 2099 + +#[repr(u8)] +pub enum Register { + Second = 0x00, + Minute = 0x02, + Hour = 0x04, + Day = 0x07, + Month = 0x08, + Year = 0x09, + A = 0x0A, + B = 0x0B, + C = 0x0C, +} + +#[repr(u8)] +pub enum Interrupt { + Periodic = 1 << 6, + Alarm = 1 << 5, + Update = 1 << 4, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RTC { + pub year: u16, + pub month: u8, + pub day: u8, + pub hour: u8, + pub minute: u8, + pub second: u8, +} + +impl RTC { + pub fn new() -> Self { + CMOS::new().rtc() + } + + pub fn size() -> usize { + DATE_TIME_LEN + } + + pub fn sync(&mut self) { + *self = RTC::new(); + } +} + +impl FileIO for RTC { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.sync(); + let date = Date::try_from_ymd( + self.year.into(), self.month, self.day + ).map_err(|_| ())?; + let date_time = date.try_with_hms( + self.hour, self.minute, self.second + ).map_err(|_| ())?; + let out = date_time.format(DATE_TIME); + buf.copy_from_slice(out.as_bytes()); + Ok(out.len()) + } + + fn write(&mut self, buf: &[u8]) -> Result { + let s = String::from_utf8_lossy(buf); + let s = s.trim_end(); + if s.len() != RTC::size() { + return Err(()); + } + let date_time = PrimitiveDateTime::parse(s, DATE_TIME).map_err(|_| ())?; + self.year = date_time.year() as u16; + self.month = date_time.month(); + self.day = date_time.day(); + self.hour = date_time.hour(); + self.minute = date_time.minute(); + self.second = date_time.second(); + if self.year < RTC_CENTURY || self.year > RTC_CENTURY + 99 { + return Err(()); + } + CMOS::new().update_rtc(self); + sys::clock::init(); + Ok(buf.len()) + } + + fn close(&mut self) {} + + fn poll(&mut self, event: IO) -> bool { + match event { + IO::Read => true, + IO::Write => true, + } + } +} diff --git a/src/sys/clock.rs b/src/sys/clock.rs index 1e400779..8a42469a 100644 --- a/src/sys/clock.rs +++ b/src/sys/clock.rs @@ -1,7 +1,7 @@ use crate::api::clock::DATE_TIME_ZONE; use crate::api::fs::{FileIO, IO}; use crate::sys; -use crate::sys::cmos::CMOS; +use crate::sys::clk::CMOS; use time::{Duration, OffsetDateTime}; diff --git a/src/sys/fs/device.rs b/src/sys/fs/device.rs index ee4197bf..ae397662 100644 --- a/src/sys/fs/device.rs +++ b/src/sys/fs/device.rs @@ -5,7 +5,7 @@ use super::{dirname, filename, realpath, FileIO, IO}; use crate::sys::ata::Drive; use crate::sys::clock::{Realtime, Uptime}; -use crate::sys::cmos::RTC; +use crate::sys::clk::RTC; use crate::sys::console::Console; use crate::sys::net::socket::tcp::TcpSocket; use crate::sys::net::socket::udp::UdpSocket; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index aef35894..ca153d61 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -40,7 +40,7 @@ macro_rules! log { pub mod acpi; pub mod ata; pub mod clock; -pub mod cmos; +pub mod clk; pub mod console; pub mod cpu; pub mod fs; diff --git a/src/sys/time.rs b/src/sys/time.rs index e5899fbb..bc85f49f 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -1,5 +1,5 @@ use crate::sys; -use crate::sys::cmos::CMOS; +use crate::sys::clk::CMOS; use core::hint::spin_loop; use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use x86_64::instructions::interrupts; From 3e2a337f9410fed808bc23b58e784a2d78100804 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 20 Oct 2024 16:33:12 +0200 Subject: [PATCH 2/7] Add timer to clk module --- src/lib.rs | 2 +- src/sys/ata.rs | 4 +-- src/sys/clk/mod.rs | 12 +++++++++ src/sys/clk/sleep.rs | 28 ++++++++++++++++++++ src/sys/{time.rs => clk/timer.rs} | 43 +++++++++---------------------- src/sys/clock.rs | 6 ++--- src/sys/console.rs | 4 +-- src/sys/mod.rs | 1 - src/sys/net/nic/e1000.rs | 2 +- src/sys/net/nic/pcnet.rs | 2 +- src/sys/net/socket/mod.rs | 2 +- src/sys/net/socket/tcp.rs | 12 ++++----- src/sys/net/socket/udp.rs | 8 +++--- src/sys/rng.rs | 2 +- src/sys/syscall/service.rs | 2 +- src/usr/beep.rs | 4 +-- src/usr/life.rs | 2 +- 17 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/sys/clk/sleep.rs rename src/sys/{time.rs => clk/timer.rs} (78%) diff --git a/src/lib.rs b/src/lib.rs index 984e521f..23638b29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ pub fn init(boot_info: &'static BootInfo) { sys::pic::init(); // Enable interrupts sys::serial::init(); sys::keyboard::init(); - sys::time::init(); + sys::clk::init(); let v = option_env!("MOROS_VERSION").unwrap_or(env!("CARGO_PKG_VERSION")); log!("SYS MOROS v{}", v); diff --git a/src/sys/ata.rs b/src/sys/ata.rs index 5e6e7bd2..1ddf69ca 100644 --- a/src/sys/ata.rs +++ b/src/sys/ata.rs @@ -100,7 +100,7 @@ impl Bus { } fn wait(&mut self, ns: u64) { - sys::time::nanowait(ns); + sys::clk::nanowait(ns); } fn clear_interrupt(&mut self) -> u8 { @@ -164,7 +164,7 @@ impl Bus { // Bit 7 => 1 self.drive_register.write(0xA0 | (drive << 4)) } - sys::time::nanowait(400); // Wait at least 400 ns + sys::clk::nanowait(400); // Wait at least 400 ns self.poll(Status::BSY, false)?; self.poll(Status::DRQ, false)?; Ok(()) diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index 98624191..ac8af6c4 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -1,7 +1,19 @@ mod cmos; mod rtc; +mod sleep; +mod timer; pub use cmos::CMOS; pub use rtc::RTC; +pub use sleep::{sleep, nanowait, halt}; +pub use timer::{ + ticks, time_between_ticks, pit_frequency, set_pit_frequency_divider, + last_rtc_update +}; use rtc::{Interrupt, Register, RTC_CENTURY}; +use timer::{rdtsc, CLOCKS_PER_NANOSECOND}; + +pub fn init() { + timer::init(); +} diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sleep.rs new file mode 100644 index 00000000..4ac2053c --- /dev/null +++ b/src/sys/clk/sleep.rs @@ -0,0 +1,28 @@ +use crate::sys; + +use core::sync::atomic::Ordering; +use x86_64::instructions::interrupts; + +pub fn halt() { + let disabled = !interrupts::are_enabled(); + interrupts::enable_and_hlt(); + if disabled { + interrupts::disable(); + } +} + +pub fn sleep(seconds: f64) { + let start = sys::clock::uptime(); + while sys::clock::uptime() - start < seconds { + halt(); + } +} + +pub fn nanowait(nanoseconds: u64) { + let start = super::rdtsc(); + let clock = super::CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed); + let delta = nanoseconds * clock; + while super::rdtsc() - start < delta { + core::hint::spin_loop(); + } +} diff --git a/src/sys/time.rs b/src/sys/clk/timer.rs similarity index 78% rename from src/sys/time.rs rename to src/sys/clk/timer.rs index bc85f49f..d0fd2b10 100644 --- a/src/sys/time.rs +++ b/src/sys/clk/timer.rs @@ -1,6 +1,5 @@ use crate::sys; use crate::sys::clk::CMOS; -use core::hint::spin_loop; use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use x86_64::instructions::interrupts; use x86_64::instructions::port::Port; @@ -15,7 +14,7 @@ const PIT_INTERVAL: f64 = (PIT_DIVIDER as f64) / PIT_FREQUENCY; static PIT_TICKS: AtomicUsize = AtomicUsize::new(0); static LAST_RTC_UPDATE: AtomicUsize = AtomicUsize::new(0); -static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0); +pub static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0); pub fn ticks() -> usize { PIT_TICKS.load(Ordering::Relaxed) @@ -29,34 +28,8 @@ pub fn last_rtc_update() -> usize { LAST_RTC_UPDATE.load(Ordering::Relaxed) } -pub fn halt() { - let disabled = !interrupts::are_enabled(); - interrupts::enable_and_hlt(); - if disabled { - interrupts::disable(); - } -} - -fn rdtsc() -> u64 { - unsafe { - core::arch::x86_64::_mm_lfence(); - core::arch::x86_64::_rdtsc() - } -} - -pub fn sleep(seconds: f64) { - let start = sys::clock::uptime(); - while sys::clock::uptime() - start < seconds { - halt(); - } -} - -pub fn nanowait(nanoseconds: u64) { - let start = rdtsc(); - let delta = nanoseconds * CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed); - while rdtsc() - start < delta { - spin_loop(); - } +pub fn pit_frequency() -> f64 { + PIT_FREQUENCY } /// The frequency divider must be between 0 and 65535, with 0 acting as 65536 @@ -75,6 +48,14 @@ pub fn set_pit_frequency_divider(divider: u16, channel: u8) { }); } +// Read Time Stamp Counter +pub fn rdtsc() -> u64 { + unsafe { + core::arch::x86_64::_mm_lfence(); + core::arch::x86_64::_rdtsc() + } +} + pub fn pit_interrupt_handler() { PIT_TICKS.fetch_add(1, Ordering::Relaxed); } @@ -98,7 +79,7 @@ pub fn init() { // TSC timmer let calibration_time = 250_000; // 0.25 seconds let a = rdtsc(); - sleep(calibration_time as f64 / 1e6); + super::sleep(calibration_time as f64 / 1e6); let b = rdtsc(); CLOCKS_PER_NANOSECOND.store((b - a) / calibration_time, Ordering::Relaxed); } diff --git a/src/sys/clock.rs b/src/sys/clock.rs index 8a42469a..988b5a1b 100644 --- a/src/sys/clock.rs +++ b/src/sys/clock.rs @@ -50,7 +50,7 @@ impl FileIO for Uptime { // NOTE: This clock is monotonic pub fn uptime() -> f64 { - sys::time::time_between_ticks() * sys::time::ticks() as f64 + sys::clk::time_between_ticks() * sys::clk::ticks() as f64 } #[derive(Debug, Clone)] @@ -103,8 +103,8 @@ pub fn realtime() -> f64 { + 60 * rtc.minute as u64 + rtc.second as u64; - let fract = sys::time::time_between_ticks() - * (sys::time::ticks() - sys::time::last_rtc_update()) as f64; + let fract = sys::clk::time_between_ticks() + * (sys::clk::ticks() - sys::clk::last_rtc_update()) as f64; (ts as f64) + fract } diff --git a/src/sys/console.rs b/src/sys/console.rs index a98b5bdb..7502a253 100644 --- a/src/sys/console.rs +++ b/src/sys/console.rs @@ -141,7 +141,7 @@ pub fn read_char() -> char { sys::console::disable_echo(); sys::console::enable_raw(); loop { - sys::time::halt(); + sys::clk::halt(); let res = interrupts::without_interrupts(|| { let mut stdin = STDIN.lock(); if !stdin.is_empty() { @@ -160,7 +160,7 @@ pub fn read_char() -> char { pub fn read_line() -> String { loop { - sys::time::halt(); + sys::clk::halt(); let res = interrupts::without_interrupts(|| { let mut stdin = STDIN.lock(); match stdin.chars().next_back() { diff --git a/src/sys/mod.rs b/src/sys/mod.rs index ca153d61..da62b992 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -56,5 +56,4 @@ pub mod process; pub mod rng; pub mod serial; pub mod syscall; -pub mod time; pub mod vga; diff --git a/src/sys/net/nic/e1000.rs b/src/sys/net/nic/e1000.rs index 27ebb022..5ca856e3 100644 --- a/src/sys/net/nic/e1000.rs +++ b/src/sys/net/nic/e1000.rs @@ -168,7 +168,7 @@ impl Device { // Reset device let ctrl = self.read(REG_CTRL); self.write(REG_CTRL, ctrl | CTRL_RST); // Reset - sys::time::nanowait(500); // TODO: How long should we wait? + sys::clk::nanowait(500); // TODO: How long should we wait? // Disable interrupts again self.write(REG_IMC, 0xFFFF); diff --git a/src/sys/net/nic/pcnet.rs b/src/sys/net/nic/pcnet.rs index e971d75f..dc11c200 100644 --- a/src/sys/net/nic/pcnet.rs +++ b/src/sys/net/nic/pcnet.rs @@ -229,7 +229,7 @@ impl Device { // Wait until init is done while !self.ports.read_csr_32(0).get_bit(CSR0_IDON) { - sys::time::halt(); + sys::clk::halt(); } // IDON + INTR + INIT diff --git a/src/sys/net/socket/mod.rs b/src/sys/net/socket/mod.rs index ee90bb19..a63fb34a 100644 --- a/src/sys/net/socket/mod.rs +++ b/src/sys/net/socket/mod.rs @@ -20,5 +20,5 @@ fn random_port() -> u16 { } fn wait(duration: Duration) { - sys::time::sleep((duration.total_micros() as f64) / 1000000.0); + sys::clk::sleep((duration.total_micros() as f64) / 1000000.0); } diff --git a/src/sys/net/socket/tcp.rs b/src/sys/net/socket/tcp.rs index 33fa0065..e91909f6 100644 --- a/src/sys/net/socket/tcp.rs +++ b/src/sys/net/socket/tcp.rs @@ -91,7 +91,7 @@ impl TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } } Ok(()) @@ -110,7 +110,7 @@ impl TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); Ok(()) } else { Err(()) @@ -136,7 +136,7 @@ impl TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } } else { Err(()) @@ -174,7 +174,7 @@ impl FileIO for TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } Ok(bytes) } else { @@ -208,7 +208,7 @@ impl FileIO for TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } Ok(buf.len()) } else { @@ -233,7 +233,7 @@ impl FileIO for TcpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } } } diff --git a/src/sys/net/socket/udp.rs b/src/sys/net/socket/udp.rs index ff9a24f0..8214743a 100644 --- a/src/sys/net/socket/udp.rs +++ b/src/sys/net/socket/udp.rs @@ -79,7 +79,7 @@ impl UdpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } } self.remote_endpoint = Some(IpEndpoint::new(addr, port)); @@ -122,7 +122,7 @@ impl FileIO for UdpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } Ok(bytes) } else { @@ -160,7 +160,7 @@ impl FileIO for UdpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } Ok(buf.len()) } else { @@ -185,7 +185,7 @@ impl FileIO for UdpSocket { if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) { wait(d); } - sys::time::halt(); + sys::clk::halt(); } } } diff --git a/src/sys/rng.rs b/src/sys/rng.rs index 93e73af8..2352d121 100644 --- a/src/sys/rng.rs +++ b/src/sys/rng.rs @@ -81,7 +81,7 @@ pub fn init() { } else { log!("RNG RDRAND unavailable"); let mut hasher = Sha256::new(); - hasher.update(sys::time::ticks().to_be_bytes()); + hasher.update(sys::clk::ticks().to_be_bytes()); hasher.update(sys::clock::realtime().to_be_bytes()); hasher.update(sys::clock::uptime().to_be_bytes()); seed = hasher.finalize().into(); diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index b834eadf..1bc6dd7a 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -17,7 +17,7 @@ pub fn exit(code: ExitCode) -> ExitCode { } pub fn sleep(seconds: f64) { - sys::time::sleep(seconds); + sys::clk::sleep(seconds); } pub fn delete(path: &str) -> isize { diff --git a/src/usr/beep.rs b/src/usr/beep.rs index 25261769..4fe8d256 100644 --- a/src/usr/beep.rs +++ b/src/usr/beep.rs @@ -9,9 +9,9 @@ use x86_64::instructions::port::Port; const SPEAKER_PORT: u16 = 0x61; fn start_sound(freq: f64) { - let divider = (sys::time::PIT_FREQUENCY / freq) as u16; + let divider = (sys::clk::pit_frequency() / freq) as u16; let channel = 2; - sys::time::set_pit_frequency_divider(divider, channel); + sys::clk::set_pit_frequency_divider(divider, channel); let mut speaker: Port = Port::new(SPEAKER_PORT); let tmp = unsafe { speaker.read() }; diff --git a/src/usr/life.rs b/src/usr/life.rs index ff5e6f50..98c23ca7 100644 --- a/src/usr/life.rs +++ b/src/usr/life.rs @@ -61,7 +61,7 @@ impl Game { return; } print!("{}", self); - sys::time::sleep(1.0 / self.speed); + sys::clk::sleep(1.0 / self.speed); if self.is_game_over() { continue; // Display the screen until ^C is received } From f8b368de4de04b7390ed0a8f2efae418719a3057 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 20 Oct 2024 17:20:00 +0200 Subject: [PATCH 3/7] Move clocks to clk module --- src/lib.rs | 3 +- src/sys/ata.rs | 4 +- src/sys/clk/boot.rs | 50 +++++++++++++++++++++ src/sys/{clock.rs => clk/epoch.rs} | 70 ++---------------------------- src/sys/clk/mod.rs | 18 ++++++++ src/sys/clk/rtc.rs | 2 +- src/sys/clk/sleep.rs | 4 +- src/sys/fs/device.rs | 3 +- src/sys/fs/dir.rs | 4 +- src/sys/mod.rs | 5 +-- src/sys/net/mod.rs | 2 +- src/sys/net/socket/tcp.rs | 16 +++---- src/sys/net/socket/udp.rs | 12 ++--- src/sys/rng.rs | 4 +- 14 files changed, 101 insertions(+), 96 deletions(-) create mode 100644 src/sys/clk/boot.rs rename src/sys/{clock.rs => clk/epoch.rs} (56%) diff --git a/src/lib.rs b/src/lib.rs index 23638b29..d0123b31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,8 @@ pub fn init(boot_info: &'static BootInfo) { sys::net::init(); // Require PCI sys::ata::init(); sys::fs::init(); // Require ATA - sys::clock::init(); // Require MEM + + sys::clk::log_rtc(); // Require MEM } #[allow(dead_code)] diff --git a/src/sys/ata.rs b/src/sys/ata.rs index 1ddf69ca..6fe63835 100644 --- a/src/sys/ata.rs +++ b/src/sys/ata.rs @@ -132,9 +132,9 @@ impl Bus { } fn poll(&mut self, bit: Status, val: bool) -> Result<(), ()> { - let start = sys::clock::uptime(); + let start = sys::clk::uptime(); while self.status().get_bit(bit as usize) != val { - if sys::clock::uptime() - start > 1.0 { + if sys::clk::uptime() - start > 1.0 { debug!( "ATA hanged while polling {:?} bit in status register", bit diff --git a/src/sys/clk/boot.rs b/src/sys/clk/boot.rs new file mode 100644 index 00000000..9119b98f --- /dev/null +++ b/src/sys/clk/boot.rs @@ -0,0 +1,50 @@ +use crate::api::fs::{FileIO, IO}; + +#[derive(Debug, Clone)] +pub struct Uptime; + +impl Uptime { + pub fn new() -> Self { + Self {} + } + + pub fn size() -> usize { + core::mem::size_of::() + } +} + +impl FileIO for Uptime { + fn read(&mut self, buf: &mut [u8]) -> Result { + let time = uptime().to_be_bytes(); + let n = time.len(); + if buf.len() >= n { + buf[0..n].clone_from_slice(&time); + Ok(n) + } else { + Err(()) + } + } + + fn write(&mut self, _buf: &[u8]) -> Result { + unimplemented!(); + } + + fn close(&mut self) {} + + fn poll(&mut self, event: IO) -> bool { + match event { + IO::Read => true, + IO::Write => false, + } + } +} + +// NOTE: This clock is monotonic +pub fn uptime() -> f64 { + super::time_between_ticks() * super::ticks() as f64 +} + +#[test_case] +fn test_uptime() { + assert!(uptime() > 0.0); +} diff --git a/src/sys/clock.rs b/src/sys/clk/epoch.rs similarity index 56% rename from src/sys/clock.rs rename to src/sys/clk/epoch.rs index 988b5a1b..cd2823b7 100644 --- a/src/sys/clock.rs +++ b/src/sys/clk/epoch.rs @@ -1,58 +1,11 @@ -use crate::api::clock::DATE_TIME_ZONE; -use crate::api::fs::{FileIO, IO}; -use crate::sys; -use crate::sys::clk::CMOS; +use super::CMOS; -use time::{Duration, OffsetDateTime}; +use crate::api::fs::{FileIO, IO}; const DAYS_BEFORE_MONTH: [u64; 13] = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ]; -#[derive(Debug, Clone)] -pub struct Uptime; - -impl Uptime { - pub fn new() -> Self { - Self {} - } - - pub fn size() -> usize { - core::mem::size_of::() - } -} - -impl FileIO for Uptime { - fn read(&mut self, buf: &mut [u8]) -> Result { - let time = uptime().to_be_bytes(); - let n = time.len(); - if buf.len() >= n { - buf[0..n].clone_from_slice(&time); - Ok(n) - } else { - Err(()) - } - } - - fn write(&mut self, _buf: &[u8]) -> Result { - unimplemented!(); - } - - fn close(&mut self) {} - - fn poll(&mut self, event: IO) -> bool { - match event { - IO::Read => true, - IO::Write => false, - } - } -} - -// NOTE: This clock is monotonic -pub fn uptime() -> f64 { - sys::clk::time_between_ticks() * sys::clk::ticks() as f64 -} - #[derive(Debug, Clone)] pub struct Realtime; @@ -103,8 +56,8 @@ pub fn realtime() -> f64 { + 60 * rtc.minute as u64 + rtc.second as u64; - let fract = sys::clk::time_between_ticks() - * (sys::clk::ticks() - sys::clk::last_rtc_update()) as f64; + let fract = super::time_between_ticks() + * (super::ticks() - super::last_rtc_update()) as f64; (ts as f64) + fract } @@ -132,21 +85,6 @@ fn is_leap_year(year: u64) -> bool { } } -pub fn init() { - let s = realtime(); - let ns = Duration::nanoseconds( - libm::floor(1e9 * (s - libm::floor(s))) as i64 - ); - let dt = OffsetDateTime::from_unix_timestamp(s as i64) + ns; - let rtc = dt.format(DATE_TIME_ZONE); - log!("RTC {}", rtc); -} - -#[test_case] -fn test_uptime() { - assert!(uptime() > 0.0); -} - #[test_case] fn test_realtime() { assert!(realtime() > 1234567890.0); diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index ac8af6c4..d2ed8a2b 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -1,8 +1,12 @@ mod cmos; +mod boot; +mod epoch; mod rtc; mod sleep; mod timer; +pub use boot::{uptime, Uptime}; // TODO: Rename to boot_time +pub use epoch::{realtime, Realtime}; // TODO: Rename to epoch_time pub use cmos::CMOS; pub use rtc::RTC; pub use sleep::{sleep, nanowait, halt}; @@ -14,6 +18,20 @@ pub use timer::{ use rtc::{Interrupt, Register, RTC_CENTURY}; use timer::{rdtsc, CLOCKS_PER_NANOSECOND}; +use crate::api::clock::DATE_TIME_ZONE; + +use time::{Duration, OffsetDateTime}; + pub fn init() { timer::init(); } + +pub fn log_rtc() { + let s = realtime(); + let ns = Duration::nanoseconds( + libm::floor(1e9 * (s - libm::floor(s))) as i64 + ); + let dt = OffsetDateTime::from_unix_timestamp(s as i64) + ns; + let rtc = dt.format(DATE_TIME_ZONE); + log!("RTC {}", rtc); +} diff --git a/src/sys/clk/rtc.rs b/src/sys/clk/rtc.rs index a8943f60..eb30dbe6 100644 --- a/src/sys/clk/rtc.rs +++ b/src/sys/clk/rtc.rs @@ -84,7 +84,7 @@ impl FileIO for RTC { return Err(()); } CMOS::new().update_rtc(self); - sys::clock::init(); + sys::clk::log_rtc(); Ok(buf.len()) } diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sleep.rs index 4ac2053c..0ea69772 100644 --- a/src/sys/clk/sleep.rs +++ b/src/sys/clk/sleep.rs @@ -12,8 +12,8 @@ pub fn halt() { } pub fn sleep(seconds: f64) { - let start = sys::clock::uptime(); - while sys::clock::uptime() - start < seconds { + let start = sys::clk::uptime(); + while sys::clk::uptime() - start < seconds { halt(); } } diff --git a/src/sys/fs/device.rs b/src/sys/fs/device.rs index ae397662..ba9111ec 100644 --- a/src/sys/fs/device.rs +++ b/src/sys/fs/device.rs @@ -4,8 +4,7 @@ use super::file::File; use super::{dirname, filename, realpath, FileIO, IO}; use crate::sys::ata::Drive; -use crate::sys::clock::{Realtime, Uptime}; -use crate::sys::clk::RTC; +use crate::sys::clk::{RTC, Realtime, Uptime}; use crate::sys::console::Console; use crate::sys::net::socket::tcp::TcpSocket; use crate::sys::net::socket::udp::UdpSocket; diff --git a/src/sys/fs/dir.rs b/src/sys/fs/dir.rs index c5e0fe92..a556c9e1 100644 --- a/src/sys/fs/dir.rs +++ b/src/sys/fs/dir.rs @@ -135,7 +135,7 @@ impl Dir { let entry_kind = kind as u8; let entry_addr = entry_block.addr(); let entry_size = 0u32; - let entry_time = sys::clock::realtime() as u64; + let entry_time = sys::clk::realtime() as u64; let entry_name = truncate(name, u8::MAX as usize); let n = entry_name.len(); let i = entries.block_offset(); @@ -193,7 +193,7 @@ impl Dir { } pub fn update_entry(&self, name: &str, size: u32) { - let time = sys::clock::realtime() as u64; + let time = sys::clk::realtime() as u64; let mut entries = self.entries(); for entry in &mut entries { if entry.name() == name { diff --git a/src/sys/mod.rs b/src/sys/mod.rs index da62b992..48ea590b 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -20,7 +20,7 @@ macro_rules! debug { macro_rules! log { ($($arg:tt)*) => ({ if !cfg!(test) { - let uptime = $crate::sys::clock::uptime(); + let uptime = $crate::sys::clk::uptime(); let csi_color = $crate::api::console::Style::color("lime"); let csi_reset = $crate::api::console::Style::reset(); $crate::sys::console::print_fmt(format_args!( @@ -28,7 +28,7 @@ macro_rules! log { csi_color, uptime, csi_reset, format_args!($($arg)*) )); - let realtime = $crate::sys::clock::realtime(); + let realtime = $crate::sys::clk::realtime(); $crate::sys::log::write_fmt(format_args!( "[{:.6}] {}\n", realtime, format_args!($($arg)*) @@ -39,7 +39,6 @@ macro_rules! log { pub mod acpi; pub mod ata; -pub mod clock; pub mod clk; pub mod console; pub mod cpu; diff --git a/src/sys/net/mod.rs b/src/sys/net/mod.rs index 481c7151..17c8d2b6 100644 --- a/src/sys/net/mod.rs +++ b/src/sys/net/mod.rs @@ -28,7 +28,7 @@ pub enum SocketStatus { } fn time() -> Instant { - Instant::from_micros((sys::clock::realtime() * 1000000.0) as i64) + Instant::from_micros((sys::clk::realtime() * 1000000.0) as i64) } #[derive(Clone)] diff --git a/src/sys/net/socket/tcp.rs b/src/sys/net/socket/tcp.rs index e91909f6..d4019d11 100644 --- a/src/sys/net/socket/tcp.rs +++ b/src/sys/net/socket/tcp.rs @@ -56,10 +56,10 @@ impl TcpSocket { pub fn connect(&mut self, addr: IpAddress, port: u16) -> Result<(), ()> { let mut connecting = false; let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -119,10 +119,10 @@ impl TcpSocket { pub fn accept(&mut self) -> Result { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -147,12 +147,12 @@ impl TcpSocket { impl FileIO for TcpSocket { fn read(&mut self, buf: &mut [u8]) -> Result { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); let mut bytes = 0; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); @@ -184,12 +184,12 @@ impl FileIO for TcpSocket { fn write(&mut self, buf: &[u8]) -> Result { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); let mut sent = false; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); diff --git a/src/sys/net/socket/udp.rs b/src/sys/net/socket/udp.rs index 8214743a..41da3780 100644 --- a/src/sys/net/socket/udp.rs +++ b/src/sys/net/socket/udp.rs @@ -60,10 +60,10 @@ impl UdpSocket { pub fn connect(&mut self, addr: IpAddress, port: u16) -> Result<(), ()> { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -98,12 +98,12 @@ impl UdpSocket { impl FileIO for UdpSocket { fn read(&mut self, buf: &mut [u8]) -> Result { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let bytes; let mut sockets = SOCKETS.lock(); loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); @@ -132,12 +132,12 @@ impl FileIO for UdpSocket { fn write(&mut self, buf: &[u8]) -> Result { let timeout = 5.0; - let started = sys::clock::realtime(); + let started = sys::clk::realtime(); let mut sent = false; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clock::realtime() - started > timeout { + if sys::clk::realtime() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); diff --git a/src/sys/rng.rs b/src/sys/rng.rs index 2352d121..25c88b88 100644 --- a/src/sys/rng.rs +++ b/src/sys/rng.rs @@ -82,8 +82,8 @@ pub fn init() { log!("RNG RDRAND unavailable"); let mut hasher = Sha256::new(); hasher.update(sys::clk::ticks().to_be_bytes()); - hasher.update(sys::clock::realtime().to_be_bytes()); - hasher.update(sys::clock::uptime().to_be_bytes()); + hasher.update(sys::clk::realtime().to_be_bytes()); + hasher.update(sys::clk::uptime().to_be_bytes()); seed = hasher.finalize().into(); } From 1e206145cd8e777dfd3749e16b14135794bc0168 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 20 Oct 2024 17:54:26 +0200 Subject: [PATCH 4/7] Rename uptime and realtime to boot and epoch time --- doc/lisp.md | 3 ++- doc/manual.md | 16 ++++++++-------- doc/network.md | 2 +- dsk/lib/lisp/file.lsp | 12 ++++++------ dsk/tmp/lisp/geotime.lsp | 2 +- src/api/clock.rs | 8 ++++---- src/api/fs.rs | 6 +++--- src/api/time.rs | 2 +- src/bin/geocal.rs | 2 +- src/bin/geodate.rs | 2 +- src/sys/ata.rs | 4 ++-- src/sys/clk/boot.rs | 14 +++++++------- src/sys/clk/epoch.rs | 14 +++++++------- src/sys/clk/mod.rs | 6 +++--- src/sys/clk/sleep.rs | 4 ++-- src/sys/fs/device.rs | 38 +++++++++++++++++++------------------- src/sys/fs/dir.rs | 4 ++-- src/sys/mod.rs | 8 ++++---- src/sys/net/mod.rs | 2 +- src/sys/net/socket/tcp.rs | 16 ++++++++-------- src/sys/net/socket/udp.rs | 12 ++++++------ src/sys/rng.rs | 4 ++-- src/usr/chess.rs | 2 +- src/usr/dhcp.rs | 6 +++--- src/usr/geodate.rs | 2 +- src/usr/httpd.rs | 2 +- src/usr/install.rs | 6 +++--- src/usr/net.rs | 2 +- src/usr/time.rs | 4 ++-- www/lisp.html | 3 ++- www/manual.html | 16 ++++++++-------- www/network.html | 2 +- 32 files changed, 114 insertions(+), 112 deletions(-) diff --git a/doc/lisp.md b/doc/lisp.md index 98370150..509bf092 100644 --- a/doc/lisp.md +++ b/doc/lisp.md @@ -79,7 +79,7 @@ MOROS Lisp is a Lisp-1 dialect inspired by Scheme, Clojure, and Ruby! - `read`, `write`, `append` - `read-binary`, `write-binary`, `append-binary` - `read-line`, `read-char` -- `uptime`, `realtime` +- `clock/boot`, `clock/epoch` - `p`, `print`, `eprint`, `error` ### Math Library @@ -176,6 +176,7 @@ Would produce the following output: ### Unreleased - Add `dirname`, `filename`, `eprint`, and `error` functions +- Rename `uptime` to `clk/boot` and `realtime` to `clk/epoch` ### 0.7.1 (2024-06-20) - Add `floor`, `ceil`, and `round` functions diff --git a/doc/manual.md b/doc/manual.md index 182c071d..6ad1caf1 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -85,9 +85,9 @@ commands to test the system or `install` to setup the Created '/dev/ata/1/0' Created '/dev/ata/1/1' Created '/dev/clk' - Created '/dev/clk/uptime' - Created '/dev/clk/realtime' - Created '/dev/rtc' + Created '/dev/clk/boot' + Created '/dev/clk/epoch' + Created '/dev/clk/rtc' Created '/dev/null' Created '/dev/random' Created '/dev/console' @@ -270,7 +270,7 @@ You can print the date with `date`: You can update the real time clock by writing the correct time to its device file: - > print "2023-03-21 10:00:00" => /dev/rtc + > print "2023-03-21 10:00:00" => /dev/clk/rtc > date 2023-03-21 10:00:00 +0000 @@ -297,12 +297,12 @@ Add `env TZ 7200` to `/ini/boot.sh` before `shell` to save the timezone: There's a device file to get the number of seconds elapsed since Unix Epoch: - > read /dev/clk/realtime + > read /dev/clk/epoch 1682105344.624905 And another one since boot: - > read /dev/clk/uptime + > read /dev/clk/boot 1169.384929 ## Aliases @@ -312,7 +312,7 @@ You can add custom commands to the shell with the `alias` command. For example you can define an `uptime` command that will read the device file described above: - > alias uptime "read /dev/clk/uptime" + > alias uptime "read /dev/clk/boot" > uptime 1406.304852 @@ -377,5 +377,5 @@ There is also a `ntp` script to synchronize the clock over the network: > ntp 2023-03-21 10:00:00 - > ntp => /dev/rtc + > ntp => /dev/clk/rtc [12.111156] RTC 2023-03-21 10:00:00 +0000 diff --git a/doc/network.md b/doc/network.md index 221b0bba..c4906ab0 100644 --- a/doc/network.md +++ b/doc/network.md @@ -163,5 +163,5 @@ passed as an argument or defined in `/ini/ntp`: It can be used to synchronize the real-time clock (RTC): - > ntp => /dev/rtc + > ntp => /dev/clk/rtc [42.123456] RTC 2023-03-21 10:00:00 +0000 diff --git a/dsk/lib/lisp/file.lsp b/dsk/lib/lisp/file.lsp index 0fa6f1ee..bac39f98 100644 --- a/dsk/lib/lisp/file.lsp +++ b/dsk/lib/lisp/file.lsp @@ -75,13 +75,13 @@ # Clocks -(def (uptime) - "Returns the current value of the uptime clock" - (binary->number (read-binary "/dev/clk/uptime") "float")) +(def (clock/boot) + "Returns the number of seconds since boot" + (binary->number (read-binary "/dev/clk/boot") "float")) -(def (realtime) - "Returns the current value of the realtime clock" - (binary->number (read-binary "/dev/clk/realtime") "float")) +(def (clock/epoch) + "Returns the number of seconds since epoch" + (binary->number (read-binary "/dev/clk/epoch") "float")) # Path diff --git a/dsk/tmp/lisp/geotime.lsp b/dsk/tmp/lisp/geotime.lsp index 72e89467..a4cd4863 100644 --- a/dsk/tmp/lisp/geotime.lsp +++ b/dsk/tmp/lisp/geotime.lsp @@ -32,7 +32,7 @@ (print (if (= (len args) 1) - (geotime (str->num (first args)) (realtime)) + (geotime (str->num (first args)) (clk/epoch)) (if (= (len args) 2) (geotime (str->num (first args)) (str->num (second args))) "Usage: geotime []"))) diff --git a/src/api/clock.rs b/src/api/clock.rs index f84bac50..6d7ba833 100644 --- a/src/api/clock.rs +++ b/src/api/clock.rs @@ -18,10 +18,10 @@ fn read_float(path: &str) -> f64 { 0.0 } -pub fn uptime() -> f64 { - read_float("/dev/clk/uptime") +pub fn boot_time() -> f64 { + read_float("/dev/clk/boot") } -pub fn realtime() -> f64 { - read_float("/dev/clk/realtime") +pub fn epoch_time() -> f64 { + read_float("/dev/clk/epoch") } diff --git a/src/api/fs.rs b/src/api/fs.rs index 0841f900..3cf255a8 100644 --- a/src/api/fs.rs +++ b/src/api/fs.rs @@ -161,9 +161,9 @@ fn device_type(name: &str) -> Result { "file" => Ok(DeviceType::File), "console" => Ok(DeviceType::Console), "random" => Ok(DeviceType::Random), - "uptime" => Ok(DeviceType::Uptime), - "realtime" => Ok(DeviceType::Realtime), - "rtc" => Ok(DeviceType::RTC), + "clk-boot" => Ok(DeviceType::BootTime), + "clk-epoch" => Ok(DeviceType::EpochTime), + "clk-rtc" => Ok(DeviceType::RTC), "tcp" => Ok(DeviceType::TcpSocket), "udp" => Ok(DeviceType::UdpSocket), "vga-buffer" => Ok(DeviceType::VgaBuffer), diff --git a/src/api/time.rs b/src/api/time.rs index 9f9b133c..63a01926 100644 --- a/src/api/time.rs +++ b/src/api/time.rs @@ -8,7 +8,7 @@ pub fn now() -> OffsetDateTime { } pub fn now_utc() -> OffsetDateTime { - let s = clock::realtime(); // Since Unix Epoch + let s = clock::epoch_time(); // Since Unix Epoch let ns = Duration::nanoseconds( libm::floor(1e9 * (s - libm::floor(s))) as i64 ); diff --git a/src/bin/geocal.rs b/src/bin/geocal.rs index 775075d6..6c2aec5b 100644 --- a/src/bin/geocal.rs +++ b/src/bin/geocal.rs @@ -37,7 +37,7 @@ fn main(args: &[&str]) { let timestamp = if args.len() == 4 { args[3].parse().unwrap() } else { - clock::realtime() as i64 + clock::epoch_time() as i64 }; let week; diff --git a/src/bin/geodate.rs b/src/bin/geodate.rs index 10aa70e8..ae74b509 100644 --- a/src/bin/geodate.rs +++ b/src/bin/geodate.rs @@ -21,7 +21,7 @@ fn main(args: &[&str]) { let timestamp = if args.len() == 3 { args[2].parse().expect("Could not parse timestamp") } else { - clock::realtime() + clock::epoch_time() }; let t = geodate::get_formatted_date(format, timestamp as i64, longitude); diff --git a/src/sys/ata.rs b/src/sys/ata.rs index 6fe63835..56d4fb5f 100644 --- a/src/sys/ata.rs +++ b/src/sys/ata.rs @@ -132,9 +132,9 @@ impl Bus { } fn poll(&mut self, bit: Status, val: bool) -> Result<(), ()> { - let start = sys::clk::uptime(); + let start = sys::clk::boot_time(); while self.status().get_bit(bit as usize) != val { - if sys::clk::uptime() - start > 1.0 { + if sys::clk::boot_time() - start > 1.0 { debug!( "ATA hanged while polling {:?} bit in status register", bit diff --git a/src/sys/clk/boot.rs b/src/sys/clk/boot.rs index 9119b98f..ab2c52ab 100644 --- a/src/sys/clk/boot.rs +++ b/src/sys/clk/boot.rs @@ -1,9 +1,9 @@ use crate::api::fs::{FileIO, IO}; #[derive(Debug, Clone)] -pub struct Uptime; +pub struct BootTime; -impl Uptime { +impl BootTime { pub fn new() -> Self { Self {} } @@ -13,9 +13,9 @@ impl Uptime { } } -impl FileIO for Uptime { +impl FileIO for BootTime { fn read(&mut self, buf: &mut [u8]) -> Result { - let time = uptime().to_be_bytes(); + let time = boot_time().to_be_bytes(); let n = time.len(); if buf.len() >= n { buf[0..n].clone_from_slice(&time); @@ -40,11 +40,11 @@ impl FileIO for Uptime { } // NOTE: This clock is monotonic -pub fn uptime() -> f64 { +pub fn boot_time() -> f64 { super::time_between_ticks() * super::ticks() as f64 } #[test_case] -fn test_uptime() { - assert!(uptime() > 0.0); +fn test_boot_time() { + assert!(boot_time() > 0.0); } diff --git a/src/sys/clk/epoch.rs b/src/sys/clk/epoch.rs index cd2823b7..c0798591 100644 --- a/src/sys/clk/epoch.rs +++ b/src/sys/clk/epoch.rs @@ -7,9 +7,9 @@ const DAYS_BEFORE_MONTH: [u64; 13] = [ ]; #[derive(Debug, Clone)] -pub struct Realtime; +pub struct EpochTime; -impl Realtime { +impl EpochTime { pub fn new() -> Self { Self {} } @@ -19,9 +19,9 @@ impl Realtime { } } -impl FileIO for Realtime { +impl FileIO for EpochTime { fn read(&mut self, buf: &mut [u8]) -> Result { - let time = realtime().to_be_bytes(); + let time = epoch_time().to_be_bytes(); let n = time.len(); if buf.len() >= n { buf[0..n].clone_from_slice(&time); @@ -46,7 +46,7 @@ impl FileIO for Realtime { } // NOTE: This clock is not monotonic -pub fn realtime() -> f64 { +pub fn epoch_time() -> f64 { let rtc = CMOS::new().rtc(); // Assuming GMT let ts = 86400 * days_before_year(rtc.year as u64) @@ -86,6 +86,6 @@ fn is_leap_year(year: u64) -> bool { } #[test_case] -fn test_realtime() { - assert!(realtime() > 1234567890.0); +fn test_epoch_time() { + assert!(epoch_time() > 1234567890.0); } diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index d2ed8a2b..827b9a60 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -5,8 +5,8 @@ mod rtc; mod sleep; mod timer; -pub use boot::{uptime, Uptime}; // TODO: Rename to boot_time -pub use epoch::{realtime, Realtime}; // TODO: Rename to epoch_time +pub use boot::{boot_time, BootTime}; // TODO: Rename to boot_time +pub use epoch::{epoch_time, EpochTime}; // TODO: Rename to epoch_time pub use cmos::CMOS; pub use rtc::RTC; pub use sleep::{sleep, nanowait, halt}; @@ -27,7 +27,7 @@ pub fn init() { } pub fn log_rtc() { - let s = realtime(); + let s = epoch_time(); let ns = Duration::nanoseconds( libm::floor(1e9 * (s - libm::floor(s))) as i64 ); diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sleep.rs index 0ea69772..86b708ad 100644 --- a/src/sys/clk/sleep.rs +++ b/src/sys/clk/sleep.rs @@ -12,8 +12,8 @@ pub fn halt() { } pub fn sleep(seconds: f64) { - let start = sys::clk::uptime(); - while sys::clk::uptime() - start < seconds { + let start = sys::clk::boot_time(); + while sys::clk::boot_time() - start < seconds { halt(); } } diff --git a/src/sys/fs/device.rs b/src/sys/fs/device.rs index ba9111ec..888a7607 100644 --- a/src/sys/fs/device.rs +++ b/src/sys/fs/device.rs @@ -4,7 +4,7 @@ use super::file::File; use super::{dirname, filename, realpath, FileIO, IO}; use crate::sys::ata::Drive; -use crate::sys::clk::{RTC, Realtime, Uptime}; +use crate::sys::clk::{RTC, EpochTime, BootTime}; use crate::sys::console::Console; use crate::sys::net::socket::tcp::TcpSocket; use crate::sys::net::socket::udp::UdpSocket; @@ -23,8 +23,8 @@ pub enum DeviceType { File = 1, Console = 2, Random = 3, - Uptime = 4, - Realtime = 5, + BootTime = 4, + EpochTime = 5, RTC = 6, TcpSocket = 7, UdpSocket = 8, @@ -44,8 +44,8 @@ impl TryFrom<&[u8]> for DeviceType { 1 => Ok(DeviceType::File), 2 => Ok(DeviceType::Console), 3 => Ok(DeviceType::Random), - 4 => Ok(DeviceType::Uptime), - 5 => Ok(DeviceType::Realtime), + 4 => Ok(DeviceType::BootTime), + 5 => Ok(DeviceType::EpochTime), 6 => Ok(DeviceType::RTC), 7 => Ok(DeviceType::TcpSocket), 8 => Ok(DeviceType::UdpSocket), @@ -66,8 +66,8 @@ impl DeviceType { pub fn buf(self) -> Vec { let len = match self { DeviceType::RTC => RTC::size(), - DeviceType::Uptime => Uptime::size(), - DeviceType::Realtime => Realtime::size(), + DeviceType::BootTime => BootTime::size(), + DeviceType::EpochTime => EpochTime::size(), DeviceType::Console => Console::size(), DeviceType::TcpSocket => TcpSocket::size(), DeviceType::UdpSocket => UdpSocket::size(), @@ -89,8 +89,8 @@ pub enum Device { File(File), Console(Console), Random(Random), - Uptime(Uptime), - Realtime(Realtime), + BootTime(BootTime), + EpochTime(EpochTime), RTC(RTC), TcpSocket(TcpSocket), UdpSocket(UdpSocket), @@ -110,8 +110,8 @@ impl TryFrom<&[u8]> for Device { DeviceType::File => Ok(Device::File(File::new())), DeviceType::Console => Ok(Device::Console(Console::new())), DeviceType::Random => Ok(Device::Random(Random::new())), - DeviceType::Uptime => Ok(Device::Uptime(Uptime::new())), - DeviceType::Realtime => Ok(Device::Realtime(Realtime::new())), + DeviceType::BootTime => Ok(Device::BootTime(BootTime::new())), + DeviceType::EpochTime => Ok(Device::EpochTime(EpochTime::new())), DeviceType::RTC => Ok(Device::RTC(RTC::new())), DeviceType::TcpSocket => Ok(Device::TcpSocket(TcpSocket::new())), DeviceType::UdpSocket => Ok(Device::UdpSocket(UdpSocket::new())), @@ -172,8 +172,8 @@ impl FileIO for Device { Device::File(io) => io.read(buf), Device::Console(io) => io.read(buf), Device::Random(io) => io.read(buf), - Device::Uptime(io) => io.read(buf), - Device::Realtime(io) => io.read(buf), + Device::BootTime(io) => io.read(buf), + Device::EpochTime(io) => io.read(buf), Device::RTC(io) => io.read(buf), Device::TcpSocket(io) => io.read(buf), Device::UdpSocket(io) => io.read(buf), @@ -191,8 +191,8 @@ impl FileIO for Device { Device::File(io) => io.write(buf), Device::Console(io) => io.write(buf), Device::Random(io) => io.write(buf), - Device::Uptime(io) => io.write(buf), - Device::Realtime(io) => io.write(buf), + Device::BootTime(io) => io.write(buf), + Device::EpochTime(io) => io.write(buf), Device::RTC(io) => io.write(buf), Device::TcpSocket(io) => io.write(buf), Device::UdpSocket(io) => io.write(buf), @@ -210,8 +210,8 @@ impl FileIO for Device { Device::File(io) => io.close(), Device::Console(io) => io.close(), Device::Random(io) => io.close(), - Device::Uptime(io) => io.close(), - Device::Realtime(io) => io.close(), + Device::BootTime(io) => io.close(), + Device::EpochTime(io) => io.close(), Device::RTC(io) => io.close(), Device::TcpSocket(io) => io.close(), Device::UdpSocket(io) => io.close(), @@ -229,8 +229,8 @@ impl FileIO for Device { Device::File(io) => io.poll(event), Device::Console(io) => io.poll(event), Device::Random(io) => io.poll(event), - Device::Uptime(io) => io.poll(event), - Device::Realtime(io) => io.poll(event), + Device::BootTime(io) => io.poll(event), + Device::EpochTime(io) => io.poll(event), Device::RTC(io) => io.poll(event), Device::TcpSocket(io) => io.poll(event), Device::UdpSocket(io) => io.poll(event), diff --git a/src/sys/fs/dir.rs b/src/sys/fs/dir.rs index a556c9e1..a90a997b 100644 --- a/src/sys/fs/dir.rs +++ b/src/sys/fs/dir.rs @@ -135,7 +135,7 @@ impl Dir { let entry_kind = kind as u8; let entry_addr = entry_block.addr(); let entry_size = 0u32; - let entry_time = sys::clk::realtime() as u64; + let entry_time = sys::clk::epoch_time() as u64; let entry_name = truncate(name, u8::MAX as usize); let n = entry_name.len(); let i = entries.block_offset(); @@ -193,7 +193,7 @@ impl Dir { } pub fn update_entry(&self, name: &str, size: u32) { - let time = sys::clk::realtime() as u64; + let time = sys::clk::epoch_time() as u64; let mut entries = self.entries(); for entry in &mut entries { if entry.name() == name { diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 48ea590b..233c9638 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -20,18 +20,18 @@ macro_rules! debug { macro_rules! log { ($($arg:tt)*) => ({ if !cfg!(test) { - let uptime = $crate::sys::clk::uptime(); + let time = $crate::sys::clk::boot_time(); let csi_color = $crate::api::console::Style::color("lime"); let csi_reset = $crate::api::console::Style::reset(); $crate::sys::console::print_fmt(format_args!( "{}[{:.6}]{} {}\n", - csi_color, uptime, csi_reset, format_args!($($arg)*) + csi_color, time, csi_reset, format_args!($($arg)*) )); - let realtime = $crate::sys::clk::realtime(); + let time = $crate::sys::clk::epoch_time(); $crate::sys::log::write_fmt(format_args!( "[{:.6}] {}\n", - realtime, format_args!($($arg)*) + time, format_args!($($arg)*) )); } }); diff --git a/src/sys/net/mod.rs b/src/sys/net/mod.rs index 17c8d2b6..e4a26e75 100644 --- a/src/sys/net/mod.rs +++ b/src/sys/net/mod.rs @@ -28,7 +28,7 @@ pub enum SocketStatus { } fn time() -> Instant { - Instant::from_micros((sys::clk::realtime() * 1000000.0) as i64) + Instant::from_micros((sys::clk::epoch_time() * 1000000.0) as i64) } #[derive(Clone)] diff --git a/src/sys/net/socket/tcp.rs b/src/sys/net/socket/tcp.rs index d4019d11..55118577 100644 --- a/src/sys/net/socket/tcp.rs +++ b/src/sys/net/socket/tcp.rs @@ -56,10 +56,10 @@ impl TcpSocket { pub fn connect(&mut self, addr: IpAddress, port: u16) -> Result<(), ()> { let mut connecting = false; let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -119,10 +119,10 @@ impl TcpSocket { pub fn accept(&mut self) -> Result { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -147,12 +147,12 @@ impl TcpSocket { impl FileIO for TcpSocket { fn read(&mut self, buf: &mut [u8]) -> Result { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); let mut bytes = 0; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); @@ -184,12 +184,12 @@ impl FileIO for TcpSocket { fn write(&mut self, buf: &[u8]) -> Result { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); let mut sent = false; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); diff --git a/src/sys/net/socket/udp.rs b/src/sys/net/socket/udp.rs index 41da3780..0573c65c 100644 --- a/src/sys/net/socket/udp.rs +++ b/src/sys/net/socket/udp.rs @@ -60,10 +60,10 @@ impl UdpSocket { pub fn connect(&mut self, addr: IpAddress, port: u16) -> Result<(), ()> { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } let mut sockets = SOCKETS.lock(); @@ -98,12 +98,12 @@ impl UdpSocket { impl FileIO for UdpSocket { fn read(&mut self, buf: &mut [u8]) -> Result { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let bytes; let mut sockets = SOCKETS.lock(); loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); @@ -132,12 +132,12 @@ impl FileIO for UdpSocket { fn write(&mut self, buf: &[u8]) -> Result { let timeout = 5.0; - let started = sys::clk::realtime(); + let started = sys::clk::epoch_time(); let mut sent = false; if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() { let mut sockets = SOCKETS.lock(); loop { - if sys::clk::realtime() - started > timeout { + if sys::clk::epoch_time() - started > timeout { return Err(()); } iface.poll(sys::net::time(), device, &mut sockets); diff --git a/src/sys/rng.rs b/src/sys/rng.rs index 25c88b88..d4fb29d9 100644 --- a/src/sys/rng.rs +++ b/src/sys/rng.rs @@ -82,8 +82,8 @@ pub fn init() { log!("RNG RDRAND unavailable"); let mut hasher = Sha256::new(); hasher.update(sys::clk::ticks().to_be_bytes()); - hasher.update(sys::clk::realtime().to_be_bytes()); - hasher.update(sys::clk::uptime().to_be_bytes()); + hasher.update(sys::clk::epoch_time().to_be_bytes()); + hasher.update(sys::clk::boot_time().to_be_bytes()); seed = hasher.finalize().into(); } diff --git a/src/usr/chess.rs b/src/usr/chess.rs index f8082055..2782e85b 100644 --- a/src/usr/chess.rs +++ b/src/usr/chess.rs @@ -53,7 +53,7 @@ fn update_autocomplete(prompt: &mut Prompt, game: &mut Game) { } fn system_time() -> u128 { - (api::clock::realtime() * 1000.0) as u128 + (api::clock::epoch_time() * 1000.0) as u128 } struct Chess { diff --git a/src/usr/dhcp.rs b/src/usr/dhcp.rs index 0be39fe3..3c90a4f8 100644 --- a/src/usr/dhcp.rs +++ b/src/usr/dhcp.rs @@ -34,9 +34,9 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { debug!("DHCP Discover transmitted"); } let timeout = 30.0; - let started = clock::realtime(); + let started = clock::epoch_time(); loop { - if clock::realtime() - started > timeout { + if clock::epoch_time() - started > timeout { error!("Timeout reached"); return Err(ExitCode::Failure); } @@ -45,7 +45,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { return Err(ExitCode::Failure); } - let ms = (clock::realtime() * 1000000.0) as i64; + let ms = (clock::epoch_time() * 1000000.0) as i64; let time = Instant::from_micros(ms); iface.poll(time, device, &mut sockets); let event = sockets.get_mut::(dhcp_handle).poll(); diff --git a/src/usr/geodate.rs b/src/usr/geodate.rs index 3ba8d38c..e5445f59 100644 --- a/src/usr/geodate.rs +++ b/src/usr/geodate.rs @@ -15,7 +15,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { let timestamp = if args.len() == 3 { args[2].parse().expect("Could not parse timestamp") } else { - clock::realtime() + clock::epoch_time() }; let t = geodate::get_formatted_date(format, timestamp as i64, longitude); diff --git a/src/usr/httpd.rs b/src/usr/httpd.rs index 7270d01c..a0406375 100644 --- a/src/usr/httpd.rs +++ b/src/usr/httpd.rs @@ -368,7 +368,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { return Ok(()); } - let ms = (clock::realtime() * 1000000.0) as i64; + let ms = (clock::epoch_time() * 1000000.0) as i64; let time = Instant::from_micros(ms); iface.poll(time, device, &mut sockets); diff --git a/src/usr/install.rs b/src/usr/install.rs index 43d58bac..d199f05e 100644 --- a/src/usr/install.rs +++ b/src/usr/install.rs @@ -54,9 +54,9 @@ pub fn copy_files(verbose: bool) { create_dev("/dev/ata/0/1", "ata-0-1", verbose); create_dev("/dev/ata/1/0", "ata-1-0", verbose); create_dev("/dev/ata/1/1", "ata-1-1", verbose); - create_dev("/dev/clk/uptime", "uptime", verbose); - create_dev("/dev/clk/realtime", "realtime", verbose); - create_dev("/dev/rtc", "rtc", verbose); + create_dev("/dev/clk/boot", "clk-boot", verbose); + create_dev("/dev/clk/epoch", "clk-epoch", verbose); + create_dev("/dev/clk/rtc", "clk-rtc", verbose); create_dev("/dev/null", "null", verbose); create_dev("/dev/random", "random", verbose); create_dev("/dev/console", "console", verbose); diff --git a/src/usr/net.rs b/src/usr/net.rs index cfab61dd..2a91542d 100644 --- a/src/usr/net.rs +++ b/src/usr/net.rs @@ -275,7 +275,7 @@ fn monitor() { } syscall::sleep(0.1); - let ms = (clock::realtime() * 1000000.0) as i64; + let ms = (clock::epoch_time() * 1000000.0) as i64; let time = Instant::from_micros(ms); iface.poll(time, device, &mut sockets); let socket = sockets.get_mut::(tcp_handle); diff --git a/src/usr/time.rs b/src/usr/time.rs index 5d0b9b8f..616d1151 100644 --- a/src/usr/time.rs +++ b/src/usr/time.rs @@ -7,9 +7,9 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> { let csi_color = Style::color("blue"); let csi_reset = Style::reset(); let cmd = args[1..].join(" "); - let start = clock::realtime(); + let start = clock::epoch_time(); let res = usr::shell::exec(&cmd); - let duration = clock::realtime() - start; + let duration = clock::epoch_time() - start; eprintln!( "{}Executed '{}' in {:.6}s{}", csi_color, cmd, duration, csi_reset diff --git a/www/lisp.html b/www/lisp.html index 08e21e65..89e1f3d6 100644 --- a/www/lisp.html +++ b/www/lisp.html @@ -104,7 +104,7 @@

File Library

  • read, write, append
  • read-binary, write-binary, append-binary
  • read-line, read-char
  • -
  • uptime, realtime
  • +
  • clock/boot, clock/epoch
  • p, print, eprint, error
  • @@ -205,6 +205,7 @@

    Unreleased

    • Add dirname, filename, eprint, and error functions
    • +
    • Rename uptime to clk/boot and realtime to clk/epoch

    0.7.1 (2024-06-20)

    diff --git a/www/manual.html b/www/manual.html index 68d440c4..babe01f2 100644 --- a/www/manual.html +++ b/www/manual.html @@ -94,9 +94,9 @@

    Installation

    Created '/dev/ata/1/0' Created '/dev/ata/1/1' Created '/dev/clk' -Created '/dev/clk/uptime' -Created '/dev/clk/realtime' -Created '/dev/rtc' +Created '/dev/clk/boot' +Created '/dev/clk/epoch' +Created '/dev/clk/rtc' Created '/dev/null' Created '/dev/random' Created '/dev/console' @@ -290,7 +290,7 @@

    Time

    You can update the real time clock by writing the correct time to its device file:

    -
    > print "2023-03-21 10:00:00" => /dev/rtc
    +    
    > print "2023-03-21 10:00:00" => /dev/clk/rtc
     
     > date
     2023-03-21 10:00:00 +0000
    @@ -320,13 +320,13 @@ 

    Time

    There's a device file to get the number of seconds elapsed since Unix Epoch:

    -
    > read /dev/clk/realtime
    +    
    > read /dev/clk/epoch
     1682105344.624905
     

    And another one since boot:

    -
    > read /dev/clk/uptime
    +    
    > read /dev/clk/boot
     1169.384929
     
    @@ -337,7 +337,7 @@

    Aliases

    For example you can define an uptime command that will read the device file described above:

    -
    > alias uptime "read /dev/clk/uptime"
    +    
    > alias uptime "read /dev/clk/boot"
     
     > uptime
     1406.304852
    @@ -407,7 +407,7 @@ 

    Network

    > ntp
     2023-03-21 10:00:00
     
    -> ntp => /dev/rtc
    +> ntp => /dev/clk/rtc
     [12.111156] RTC 2023-03-21 10:00:00 +0000
     
    diff --git a/www/network.html b/www/network.html index 73e0c199..3cd7a81e 100644 --- a/www/network.html +++ b/www/network.html @@ -188,7 +188,7 @@

    NTP

    It can be used to synchronize the real-time clock (RTC):

    -
    > ntp => /dev/rtc
    +    
    > ntp => /dev/clk/rtc
     [42.123456] RTC 2023-03-21 10:00:00 +0000
     
    From c0e5b53a3b2bab397f49b4813e76c36347adc30d Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Mon, 21 Oct 2024 11:23:13 +0200 Subject: [PATCH 5/7] Refactor module --- src/lib.rs | 2 +- src/sys/clk/boot.rs | 8 ++++++-- src/sys/clk/cmos.rs | 9 ++++++--- src/sys/clk/epoch.rs | 11 +++++++---- src/sys/clk/mod.rs | 24 +++++++++--------------- src/sys/clk/rtc.rs | 5 ++--- src/sys/clk/sleep.rs | 16 ++++++++-------- src/sys/clk/timer.rs | 31 +++++++++++++++++++------------ src/sys/serial.rs | 2 +- src/usr/beep.rs | 2 +- 10 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d0123b31..b76c3a64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ pub fn init(boot_info: &'static BootInfo) { sys::ata::init(); sys::fs::init(); // Require ATA - sys::clk::log_rtc(); // Require MEM + log!("RTC {}", sys::clk::date()); } #[allow(dead_code)] diff --git a/src/sys/clk/boot.rs b/src/sys/clk/boot.rs index ab2c52ab..ff633d30 100644 --- a/src/sys/clk/boot.rs +++ b/src/sys/clk/boot.rs @@ -1,3 +1,5 @@ +use super::timer; + use crate::api::fs::{FileIO, IO}; #[derive(Debug, Clone)] @@ -39,9 +41,11 @@ impl FileIO for BootTime { } } -// NOTE: This clock is monotonic +/// Returns the number of seconds since boot. +/// +/// This clock is monotonic. pub fn boot_time() -> f64 { - super::time_between_ticks() * super::ticks() as f64 + timer::time_between_ticks() * timer::ticks() as f64 } #[test_case] diff --git a/src/sys/clk/cmos.rs b/src/sys/clk/cmos.rs index fcd5d551..624bb0c6 100644 --- a/src/sys/clk/cmos.rs +++ b/src/sys/clk/cmos.rs @@ -1,4 +1,4 @@ -use super::{Interrupt, RTC, Register, RTC_CENTURY}; +use super::rtc::{Interrupt, RTC, Register, RTC_CENTURY}; use bit_field::BitField; use core::hint::spin_loop; @@ -107,10 +107,12 @@ impl CMOS { self.write_register(Register::Year, year as u8); } + #[allow(dead_code)] pub fn enable_periodic_interrupt(&mut self) { self.enable_interrupt(Interrupt::Periodic); } + #[allow(dead_code)] pub fn enable_alarm_interrupt(&mut self) { self.enable_interrupt(Interrupt::Alarm); } @@ -119,8 +121,9 @@ impl CMOS { self.enable_interrupt(Interrupt::Update); } - /// Rate must be between 3 and 15 - /// Resulting in the following frequency: 32768 >> (rate - 1) + // Rate must be between 3 and 15 + // Resulting in the following frequency: 32768 >> (rate - 1) + #[allow(dead_code)] pub fn set_periodic_interrupt_rate(&mut self, rate: u8) { interrupts::without_interrupts(|| { self.disable_nmi(); diff --git a/src/sys/clk/epoch.rs b/src/sys/clk/epoch.rs index c0798591..7512b444 100644 --- a/src/sys/clk/epoch.rs +++ b/src/sys/clk/epoch.rs @@ -1,4 +1,5 @@ -use super::CMOS; +use super::cmos::CMOS; +use super::timer; use crate::api::fs::{FileIO, IO}; @@ -45,7 +46,9 @@ impl FileIO for EpochTime { } } -// NOTE: This clock is not monotonic +/// Returns the number of seconds since Unix epoch (1970-01-01 00:00:00 UTC). +/// +/// This clock is not monotonic. pub fn epoch_time() -> f64 { let rtc = CMOS::new().rtc(); // Assuming GMT @@ -56,8 +59,8 @@ pub fn epoch_time() -> f64 { + 60 * rtc.minute as u64 + rtc.second as u64; - let fract = super::time_between_ticks() - * (super::ticks() - super::last_rtc_update()) as f64; + let fract = timer::time_between_ticks() + * (timer::ticks() - timer::last_rtc_update()) as f64; (ts as f64) + fract } diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index 827b9a60..8993d681 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -5,33 +5,27 @@ mod rtc; mod sleep; mod timer; -pub use boot::{boot_time, BootTime}; // TODO: Rename to boot_time -pub use epoch::{epoch_time, EpochTime}; // TODO: Rename to epoch_time -pub use cmos::CMOS; +pub use boot::{boot_time, BootTime}; +pub use epoch::{epoch_time, EpochTime}; pub use rtc::RTC; pub use sleep::{sleep, nanowait, halt}; -pub use timer::{ - ticks, time_between_ticks, pit_frequency, set_pit_frequency_divider, - last_rtc_update -}; +pub use timer::{ticks, pit_frequency, set_pit_frequency}; -use rtc::{Interrupt, Register, RTC_CENTURY}; -use timer::{rdtsc, CLOCKS_PER_NANOSECOND}; - -use crate::api::clock::DATE_TIME_ZONE; +use crate::api; +use alloc::string::String; use time::{Duration, OffsetDateTime}; pub fn init() { timer::init(); } -pub fn log_rtc() { - let s = epoch_time(); +/// Returns the current date and time. +pub fn date() -> String { + let s = epoch::epoch_time(); let ns = Duration::nanoseconds( libm::floor(1e9 * (s - libm::floor(s))) as i64 ); let dt = OffsetDateTime::from_unix_timestamp(s as i64) + ns; - let rtc = dt.format(DATE_TIME_ZONE); - log!("RTC {}", rtc); + dt.format(api::clock::DATE_TIME_ZONE) } diff --git a/src/sys/clk/rtc.rs b/src/sys/clk/rtc.rs index eb30dbe6..511ccefc 100644 --- a/src/sys/clk/rtc.rs +++ b/src/sys/clk/rtc.rs @@ -1,6 +1,5 @@ -use super::CMOS; +use super::cmos::CMOS; -use crate::sys; use crate::api::clock::{DATE_TIME, DATE_TIME_LEN}; use crate::api::fs::{FileIO, IO}; @@ -84,7 +83,7 @@ impl FileIO for RTC { return Err(()); } CMOS::new().update_rtc(self); - sys::clk::log_rtc(); + log!("RTC {}", super::date()); Ok(buf.len()) } diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sleep.rs index 86b708ad..f76af0e2 100644 --- a/src/sys/clk/sleep.rs +++ b/src/sys/clk/sleep.rs @@ -1,6 +1,6 @@ -use crate::sys; +use super::boot; +use super::timer; -use core::sync::atomic::Ordering; use x86_64::instructions::interrupts; pub fn halt() { @@ -12,17 +12,17 @@ pub fn halt() { } pub fn sleep(seconds: f64) { - let start = sys::clk::boot_time(); - while sys::clk::boot_time() - start < seconds { + let start = boot::boot_time(); + while boot::boot_time() - start < seconds { halt(); } } pub fn nanowait(nanoseconds: u64) { - let start = super::rdtsc(); - let clock = super::CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed); - let delta = nanoseconds * clock; - while super::rdtsc() - start < delta { + let start = timer::tsc(); + let freq = timer::tsc_frequency(); + let delta = nanoseconds * freq; + while timer::tsc() - start < delta { core::hint::spin_loop(); } } diff --git a/src/sys/clk/timer.rs b/src/sys/clk/timer.rs index d0fd2b10..6db40185 100644 --- a/src/sys/clk/timer.rs +++ b/src/sys/clk/timer.rs @@ -1,5 +1,8 @@ +use super::sleep; +use super::cmos::CMOS; + use crate::sys; -use crate::sys::clk::CMOS; + use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use x86_64::instructions::interrupts; use x86_64::instructions::port::Port; @@ -8,13 +11,13 @@ use x86_64::instructions::port::Port; // which will result in about 54.926 ms between ticks. // During init we will change the divider to 1193 to have about 1.000 ms // between ticks to improve time measurements accuracy. -pub const PIT_FREQUENCY: f64 = 3_579_545.0 / 3.0; // 1_193_181.666 Hz +const PIT_FREQUENCY: f64 = 3_579_545.0 / 3.0; // 1_193_181.666 Hz const PIT_DIVIDER: usize = 1193; const PIT_INTERVAL: f64 = (PIT_DIVIDER as f64) / PIT_FREQUENCY; static PIT_TICKS: AtomicUsize = AtomicUsize::new(0); static LAST_RTC_UPDATE: AtomicUsize = AtomicUsize::new(0); -pub static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0); +static TSC_FREQUENCY: AtomicU64 = AtomicU64::new(0); pub fn ticks() -> usize { PIT_TICKS.load(Ordering::Relaxed) @@ -32,8 +35,8 @@ pub fn pit_frequency() -> f64 { PIT_FREQUENCY } -/// The frequency divider must be between 0 and 65535, with 0 acting as 65536 -pub fn set_pit_frequency_divider(divider: u16, channel: u8) { +// The frequency divider must be between 0 and 65535, with 0 acting as 65536 +pub fn set_pit_frequency(divider: u16, channel: u8) { interrupts::without_interrupts(|| { let bytes = divider.to_le_bytes(); let mut cmd: Port = Port::new(0x43); @@ -48,14 +51,18 @@ pub fn set_pit_frequency_divider(divider: u16, channel: u8) { }); } -// Read Time Stamp Counter -pub fn rdtsc() -> u64 { +// Time Stamp Counter +pub fn tsc() -> u64 { unsafe { core::arch::x86_64::_mm_lfence(); core::arch::x86_64::_rdtsc() } } +pub fn tsc_frequency() -> u64 { + TSC_FREQUENCY.load(Ordering::Relaxed) +} + pub fn pit_interrupt_handler() { PIT_TICKS.fetch_add(1, Ordering::Relaxed); } @@ -69,7 +76,7 @@ pub fn init() { // PIT timmer let divider = if PIT_DIVIDER < 65536 { PIT_DIVIDER } else { 0 }; let channel = 0; - set_pit_frequency_divider(divider as u16, channel); + set_pit_frequency(divider as u16, channel); sys::idt::set_irq_handler(0, pit_interrupt_handler); // RTC timmer @@ -78,8 +85,8 @@ pub fn init() { // TSC timmer let calibration_time = 250_000; // 0.25 seconds - let a = rdtsc(); - super::sleep(calibration_time as f64 / 1e6); - let b = rdtsc(); - CLOCKS_PER_NANOSECOND.store((b - a) / calibration_time, Ordering::Relaxed); + let a = tsc(); + sleep::sleep(calibration_time as f64 / 1e6); + let b = tsc(); + TSC_FREQUENCY.store((b - a) / calibration_time, Ordering::Relaxed); } diff --git a/src/sys/serial.rs b/src/sys/serial.rs index 184b5b3b..8ea0a443 100644 --- a/src/sys/serial.rs +++ b/src/sys/serial.rs @@ -48,7 +48,7 @@ impl fmt::Write for Serial { } } -/// See https://vt100.net/emu/dec_ansi_parser +// Source: https://vt100.net/emu/dec_ansi_parser impl Perform for Serial { fn csi_dispatch(&mut self, params: &Params, _: &[u8], _: bool, c: char) { match c { diff --git a/src/usr/beep.rs b/src/usr/beep.rs index 4fe8d256..fd049d87 100644 --- a/src/usr/beep.rs +++ b/src/usr/beep.rs @@ -11,7 +11,7 @@ const SPEAKER_PORT: u16 = 0x61; fn start_sound(freq: f64) { let divider = (sys::clk::pit_frequency() / freq) as u16; let channel = 2; - sys::clk::set_pit_frequency_divider(divider, channel); + sys::clk::set_pit_frequency(divider, channel); let mut speaker: Port = Port::new(SPEAKER_PORT); let tmp = unsafe { speaker.read() }; From ce35b793efa6f69f7079c3ee4ebe24d640aadf49 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Mon, 21 Oct 2024 11:34:59 +0200 Subject: [PATCH 6/7] Refactor sync functions --- src/sys/ata.rs | 4 ++-- src/sys/clk/mod.rs | 4 ++-- src/sys/clk/{sleep.rs => sync.rs} | 16 +++++++++++++--- src/sys/clk/timer.rs | 4 ++-- src/sys/net/nic/e1000.rs | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) rename src/sys/clk/{sleep.rs => sync.rs} (51%) diff --git a/src/sys/ata.rs b/src/sys/ata.rs index 56d4fb5f..ac4e4443 100644 --- a/src/sys/ata.rs +++ b/src/sys/ata.rs @@ -100,7 +100,7 @@ impl Bus { } fn wait(&mut self, ns: u64) { - sys::clk::nanowait(ns); + sys::clk::wait(ns); } fn clear_interrupt(&mut self) -> u8 { @@ -164,7 +164,7 @@ impl Bus { // Bit 7 => 1 self.drive_register.write(0xA0 | (drive << 4)) } - sys::clk::nanowait(400); // Wait at least 400 ns + sys::clk::wait(400); // Wait at least 400 ns self.poll(Status::BSY, false)?; self.poll(Status::DRQ, false)?; Ok(()) diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index 8993d681..47c5f320 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -2,13 +2,13 @@ mod cmos; mod boot; mod epoch; mod rtc; -mod sleep; +mod sync; mod timer; pub use boot::{boot_time, BootTime}; pub use epoch::{epoch_time, EpochTime}; pub use rtc::RTC; -pub use sleep::{sleep, nanowait, halt}; +pub use sync::{halt, sleep, wait}; pub use timer::{ticks, pit_frequency, set_pit_frequency}; use crate::api; diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sync.rs similarity index 51% rename from src/sys/clk/sleep.rs rename to src/sys/clk/sync.rs index f76af0e2..ed006f2b 100644 --- a/src/sys/clk/sleep.rs +++ b/src/sys/clk/sync.rs @@ -3,6 +3,9 @@ use super::timer; use x86_64::instructions::interrupts; +/// Halts the CPU until the next interrupt. +/// +/// This function preserves interrupt state. pub fn halt() { let disabled = !interrupts::are_enabled(); interrupts::enable_and_hlt(); @@ -11,6 +14,10 @@ pub fn halt() { } } +/// Sleeps for the specified number of seconds. +/// +/// This function works by repeatedly halting the CPU until the time is +/// elapsed. pub fn sleep(seconds: f64) { let start = boot::boot_time(); while boot::boot_time() - start < seconds { @@ -18,10 +25,13 @@ pub fn sleep(seconds: f64) { } } -pub fn nanowait(nanoseconds: u64) { +/// Waits for the specified number of nanoseconds. +/// +/// This function use a busy-wait loop with the `RDTSC` and `PAUSE` +/// instructions. +pub fn wait(nanoseconds: u64) { + let delta = nanoseconds * timer::tsc_frequency(); let start = timer::tsc(); - let freq = timer::tsc_frequency(); - let delta = nanoseconds * freq; while timer::tsc() - start < delta { core::hint::spin_loop(); } diff --git a/src/sys/clk/timer.rs b/src/sys/clk/timer.rs index 6db40185..5381cb3a 100644 --- a/src/sys/clk/timer.rs +++ b/src/sys/clk/timer.rs @@ -1,4 +1,4 @@ -use super::sleep; +use super::sync; use super::cmos::CMOS; use crate::sys; @@ -86,7 +86,7 @@ pub fn init() { // TSC timmer let calibration_time = 250_000; // 0.25 seconds let a = tsc(); - sleep::sleep(calibration_time as f64 / 1e6); + sync::sleep(calibration_time as f64 / 1e6); let b = tsc(); TSC_FREQUENCY.store((b - a) / calibration_time, Ordering::Relaxed); } diff --git a/src/sys/net/nic/e1000.rs b/src/sys/net/nic/e1000.rs index 5ca856e3..83a27e31 100644 --- a/src/sys/net/nic/e1000.rs +++ b/src/sys/net/nic/e1000.rs @@ -168,7 +168,7 @@ impl Device { // Reset device let ctrl = self.read(REG_CTRL); self.write(REG_CTRL, ctrl | CTRL_RST); // Reset - sys::clk::nanowait(500); // TODO: How long should we wait? + sys::clk::wait(500); // TODO: How long should we wait? // Disable interrupts again self.write(REG_IMC, 0xFFFF); From 1013959d1bf1441fc543644705ca21b3eff9120f Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Mon, 21 Oct 2024 11:40:59 +0200 Subject: [PATCH 7/7] Return error instead of invoking the unimplemented macro in device files --- src/sys/ata.rs | 2 +- src/sys/clk/boot.rs | 2 +- src/sys/clk/epoch.rs | 2 +- src/sys/rng.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sys/ata.rs b/src/sys/ata.rs index ac4e4443..b38010f4 100644 --- a/src/sys/ata.rs +++ b/src/sys/ata.rs @@ -392,7 +392,7 @@ impl FileIO for Drive { } fn write(&mut self, _buf: &[u8]) -> Result { - unimplemented!(); + Err(()) } fn close(&mut self) { diff --git a/src/sys/clk/boot.rs b/src/sys/clk/boot.rs index ff633d30..bb9e1d64 100644 --- a/src/sys/clk/boot.rs +++ b/src/sys/clk/boot.rs @@ -28,7 +28,7 @@ impl FileIO for BootTime { } fn write(&mut self, _buf: &[u8]) -> Result { - unimplemented!(); + Err(()) } fn close(&mut self) {} diff --git a/src/sys/clk/epoch.rs b/src/sys/clk/epoch.rs index 7512b444..5ce264c0 100644 --- a/src/sys/clk/epoch.rs +++ b/src/sys/clk/epoch.rs @@ -33,7 +33,7 @@ impl FileIO for EpochTime { } fn write(&mut self, _buf: &[u8]) -> Result { - unimplemented!(); + Err(()) } fn close(&mut self) {} diff --git a/src/sys/rng.rs b/src/sys/rng.rs index d4fb29d9..d9e56f89 100644 --- a/src/sys/rng.rs +++ b/src/sys/rng.rs @@ -33,7 +33,7 @@ impl FileIO for Random { } fn write(&mut self, _buf: &[u8]) -> Result { - unimplemented!(); + Err(()) } fn close(&mut self) {}