Skip to content

Commit

Permalink
Replace clock syscalls with device files (#345)
Browse files Browse the repository at this point in the history
* Replace clock syscalls with device files

* Add missing newline to read

* Update time command
  • Loading branch information
vinc committed Jun 5, 2022
1 parent 7470240 commit e8502e3
Show file tree
Hide file tree
Showing 25 changed files with 163 additions and 109 deletions.
24 changes: 6 additions & 18 deletions doc/syscalls.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,34 +50,22 @@ pub fn info(path: &str, info: &mut FileInfo) -> isize
pub fn dup(old_handle: usize, new_handle: usize) -> isize
```

## SLEEP (0x9)
## DELETE (0x9)

```rust
pub fn sleep(seconds: f64)
```

## UPTIME (0xA)

```rust
pub fn uptime() -> f64
```

## REALTIME (0xB)

```rust
pub fn realtime() -> f64
pub fn delete(path: &str) -> isize
```

## DELETE (0xC)
## STOP (0xA)

```rust
pub fn delete(path: &str) -> isize
pub fn stop(code: usize)
```

## STOP (0xD)
## SLEEP (0xB)

```rust
pub fn stop(code: usize)
pub fn sleep(seconds: f64)
```

The system will reboot with `0xcafe` and halt with `0xdead`.
4 changes: 2 additions & 2 deletions dsk/src/bin/sleep.s
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[bits 64]
_start:
mov rax, 9 ; syscall number for SLEEP
mov rax, 0xB ; syscall number for SLEEP
mov rdi, __float64__(5.0) ; time to sleep in seconds
mov rsi, 0
mov rdx, 0
int 0x80
mov rax, 1 ; syscall number for EXIT
mov rax, 0x1 ; syscall number for EXIT
mov rdi, 0 ; no error
int 0x80
21 changes: 21 additions & 0 deletions src/api/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::api::fs;

use core::convert::TryInto;

fn read_float(path: &str) -> f64 {
if let Ok(bytes) = fs::read_to_bytes(path) {
if bytes.len() == 8 {
return f64::from_be_bytes(bytes[0..8].try_into().unwrap());
}
}

return 0.0;
}

pub fn uptime() -> f64 {
read_float("/dev/clk/uptime")
}

pub fn realtime() -> f64 {
read_float("/dev/clk/realtime")
}
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ macro_rules! error {
});
}

pub mod clock;
pub mod console;
pub mod font;
pub mod fs;
Expand Down
10 changes: 0 additions & 10 deletions src/api/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@ pub fn sleep(seconds: f64) {
unsafe { syscall!(SLEEP, seconds.to_bits()) };
}

pub fn uptime() -> f64 {
let res = unsafe { syscall!(UPTIME) };
f64::from_bits(res as u64)
}

pub fn realtime() -> f64 {
let res = unsafe { syscall!(REALTIME) };
f64::from_bits(res as u64)
}

pub fn delete(path: &str) -> Result<(), ()> {
let path_ptr = path.as_ptr() as usize;
let path_len = path.len() as usize;
Expand Down
4 changes: 2 additions & 2 deletions src/api/time.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::sys;
use crate::api::syscall;
use crate::api::clock;

use time::{OffsetDateTime, Duration, UtcOffset};

pub fn now() -> OffsetDateTime {
let s = syscall::realtime(); // Since Unix Epoch
let s = clock::realtime(); // Since Unix Epoch
let ns = Duration::nanoseconds(libm::floor(1e9 * (s - libm::floor(s))) as i64);
OffsetDateTime::from_unix_timestamp(s as i64).to_offset(offset()) + ns
}
Expand Down
51 changes: 51 additions & 0 deletions src/sys/clock.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
use crate::sys;
use crate::sys::cmos::CMOS;
use crate::sys::fs::FileIO;

use time::{OffsetDateTime, Duration};

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 {}
}
}

impl FileIO for Uptime {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
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<usize, ()> {
unimplemented!();
}
}

// NOTE: This clock is monotonic
pub fn uptime() -> f64 {
sys::time::time_between_ticks() * sys::time::ticks() as f64
}

#[derive(Debug, Clone)]
pub struct Realtime;

impl Realtime {
pub fn new() -> Self {
Self {}
}
}

impl FileIO for Realtime {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
let time = realtime().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<usize, ()> {
unimplemented!();
}
}

// NOTE: This clock is not monotonic
pub fn realtime() -> f64 {
let rtc = CMOS::new().rtc(); // Assuming GMT
Expand Down
42 changes: 30 additions & 12 deletions src/sys/fs/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,55 @@ use alloc::vec;
use alloc::vec::Vec;
use crate::sys::console::Console;
use crate::sys::random::Random;
use crate::sys::clock::{Uptime, Realtime};

#[derive(PartialEq, Clone, Copy)]
#[repr(u8)]
pub enum DeviceType {
File = 0,
Console = 1,
Random = 2,
Null = 3,
Null = 0,
File = 1,
Console = 2,
Random = 3,
Uptime = 4,
Realtime = 5,
}

// Used when creating a device
impl DeviceType {
pub fn buf(self) -> Vec<u8> {
if self == DeviceType::Console {
vec![self as u8, 0, 0, 0] // 4 bytes
} else {
vec![self as u8] // 1 byte
match self {
DeviceType::Uptime | DeviceType::Realtime => {
vec![self as u8, 0, 0, 0, 0, 0, 0, 0] // 8 bytes (f64)
}
DeviceType::Console => {
vec![self as u8, 0, 0, 0] // 4 bytes (char)
}
_ => {
vec![self as u8] // 1 byte
}
}
}
}

#[derive(Debug, Clone)]
pub enum Device {
Null,
File(File),
Console(Console),
Random(Random),
Null,
Uptime(Uptime),
Realtime(Realtime),
}

impl From<u8> for Device {
fn from(i: u8) -> Self {
match i {
i if i == DeviceType::Null as u8 => Device::Null,
i if i == DeviceType::File as u8 => Device::File(File::new()),
i if i == DeviceType::Console as u8 => Device::Console(Console::new()),
i if i == DeviceType::Random as u8 => Device::Random(Random::new()),
i if i == DeviceType::Null as u8 => Device::Null,
i if i == DeviceType::Uptime as u8 => Device::Uptime(Uptime::new()),
i if i == DeviceType::Realtime as u8 => Device::Realtime(Realtime::new()),
_ => unimplemented!(),
}
}
Expand Down Expand Up @@ -80,19 +94,23 @@ impl Device {
impl FileIO for Device {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
match self {
Device::Null => Err(()),
Device::File(io) => io.read(buf),
Device::Console(io) => io.read(buf),
Device::Random(io) => io.read(buf),
Device::Null => Err(()),
Device::Uptime(io) => io.read(buf),
Device::Realtime(io) => io.read(buf),
}
}

fn write(&mut self, buf: &[u8]) -> Result<usize, ()> {
match self {
Device::Null => Ok(0),
Device::File(io) => io.write(buf),
Device::Console(io) => io.write(buf),
Device::Random(io) => io.write(buf),
Device::Null => Ok(0),
Device::Uptime(io) => io.write(buf),
Device::Realtime(io) => io.write(buf),
}
}
}
6 changes: 0 additions & 6 deletions src/sys/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
service::sleep(f64::from_bits(arg1 as u64));
0
}
number::UPTIME => {
service::uptime().to_bits() as usize
}
number::REALTIME => {
service::realtime().to_bits() as usize
}
number::DELETE => {
let ptr = sys::process::ptr_from_addr(arg1 as u64);
let len = arg2;
Expand Down
8 changes: 3 additions & 5 deletions src/sys/syscall/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ pub const OPEN: usize = 0x5;
pub const CLOSE: usize = 0x6;
pub const INFO: usize = 0x7;
pub const DUP: usize = 0x8;
pub const SLEEP: usize = 0x9;
pub const UPTIME: usize = 0xA;
pub const REALTIME: usize = 0xB;
pub const DELETE: usize = 0xC;
pub const STOP: usize = 0xD;
pub const DELETE: usize = 0x9;
pub const STOP: usize = 0xA;
pub const SLEEP: usize = 0xB;
8 changes: 0 additions & 8 deletions src/sys/syscall/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ pub fn sleep(seconds: f64) {
sys::time::sleep(seconds);
}

pub fn uptime() -> f64 {
sys::clock::uptime()
}

pub fn realtime() -> f64 {
sys::clock::realtime()
}

pub fn delete(path: &str) -> isize {
if sys::fs::delete(path).is_ok() {
0
Expand Down
2 changes: 1 addition & 1 deletion src/usr/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn update_autocomplete(prompt: &mut Prompt, game: &mut Game) {
}

fn system_time() -> u128 {
(api::syscall::realtime() * 1000.0) as u128
(api::clock::realtime() * 1000.0) as u128
}

struct Chess {
Expand Down
7 changes: 4 additions & 3 deletions src/usr/dhcp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{sys, usr, debug};
use crate::api::clock;
use crate::api::syscall;
use alloc::string::ToString;
use alloc::vec::Vec;
Expand All @@ -25,9 +26,9 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
debug!("DHCP Discover transmitted");
}
let timeout = 30.0;
let started = syscall::realtime();
let started = clock::realtime();
loop {
if syscall::realtime() - started > timeout {
if clock::realtime() - started > timeout {
error!("Timeout reached");
iface.remove_socket(dhcp_handle);
return usr::shell::ExitCode::CommandError;
Expand All @@ -38,7 +39,7 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
return usr::shell::ExitCode::CommandError;
}

let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) {
error!("Network Error: {}", e);
}
Expand Down
5 changes: 3 additions & 2 deletions src/usr/geotime.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::usr;
use crate::api::syscall;
use crate::api::clock;

use alloc::format;
use core::f64::consts::PI;

Expand All @@ -14,7 +15,7 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
let timestamp = if args.len() == 3 {
args[2].parse().expect("Could not parse timestamp")
} else {
syscall::realtime()
clock::realtime()
};

let t = geotime(longitude, timestamp);
Expand Down
7 changes: 4 additions & 3 deletions src/usr/host.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{sys, usr};
use crate::api::clock;
use crate::api::console::Style;
use crate::api::syscall;
use crate::api::random;
Expand Down Expand Up @@ -167,13 +168,13 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
let udp_handle = iface.add_socket(udp_socket);

let timeout = 5.0;
let started = syscall::realtime();
let started = clock::realtime();
loop {
if syscall::realtime() - started > timeout {
if clock::realtime() - started > timeout {
iface.remove_socket(udp_handle);
return Err(ResponseCode::NetworkError);
}
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) {
error!("Network Error: {}", e);
}
Expand Down
Loading

0 comments on commit e8502e3

Please sign in to comment.