Skip to content

Commit

Permalink
Merge pull request #1196 from hermit-os/time-abi
Browse files Browse the repository at this point in the history
fix(POSIX/time): make subsecond fields signed and use `timespec` in `stat`
  • Loading branch information
mkroening committed May 14, 2024
2 parents 56b1ac7 + 3a21dd4 commit 5764200
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 70 deletions.
19 changes: 13 additions & 6 deletions src/fs/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::fs::{
self, fuse_abi, AccessPermission, DirectoryEntry, FileAttr, NodeKind, ObjectInterface,
OpenOption, SeekWhence, VfsNode,
};
use crate::time::{time_t, timespec};

// response out layout eg @ https://github.com/zargony/fuse-rs/blob/bf6d1cf03f3277e35b580f3c7b9999255d72ecf3/src/ll/request.rs#L44
// op in/out sizes/layout: https://github.com/hanwen/go-fuse/blob/204b45dba899dfa147235c255908236d5fde2d32/fuse/opcode.go#L439
Expand Down Expand Up @@ -439,12 +440,18 @@ impl From<fuse_abi::Attr> for FileAttr {
st_size: attr.size,
st_blksize: attr.blksize as i64,
st_blocks: attr.blocks.try_into().unwrap(),
st_atime: attr.atime,
st_atime_nsec: attr.atimensec as u64,
st_mtime: attr.mtime,
st_mtime_nsec: attr.atimensec as u64,
st_ctime: attr.ctime,
st_ctime_nsec: attr.ctimensec as u64,
st_atim: timespec {
tv_sec: attr.atime as time_t,
tv_nsec: attr.atimensec as i32,
},
st_mtim: timespec {
tv_sec: attr.mtime as time_t,
tv_nsec: attr.mtimensec as i32,
},
st_ctim: timespec {
tv_sec: attr.ctime as time_t,
tv_nsec: attr.ctimensec as i32,
},
..Default::default()
}
}
Expand Down
50 changes: 22 additions & 28 deletions src/fs/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::arch;
use crate::executor::block_on;
use crate::fd::{AccessPermission, IoError, ObjectInterface, OpenOption, PollEvent};
use crate::fs::{DirectoryEntry, FileAttr, NodeKind, VfsNode};
use crate::time::timespec;

#[derive(Debug)]
pub(crate) struct RomFileInner {
Expand Down Expand Up @@ -65,9 +66,9 @@ impl ObjectInterface for RomFileInterface {
async fn async_read(&self, buf: &mut [u8]) -> Result<usize, IoError> {
{
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);
let mut guard = self.inner.write().await;
guard.attr.st_atime = microseconds / 1_000_000;
guard.attr.st_atime_nsec = (microseconds % 1_000_000) * 1000;
guard.attr.st_atim = t;
}

let vec = self.inner.read().await.data;
Expand Down Expand Up @@ -145,9 +146,9 @@ impl ObjectInterface for RamFileInterface {
async fn async_read(&self, buf: &mut [u8]) -> Result<usize, IoError> {
{
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);
let mut guard = self.inner.write().await;
guard.attr.st_atime = microseconds / 1_000_000;
guard.attr.st_atime_nsec = (microseconds % 1_000_000) * 1000;
guard.attr.st_atim = t;
}

let guard = self.inner.read().await;
Expand All @@ -172,6 +173,7 @@ impl ObjectInterface for RamFileInterface {

async fn async_write(&self, buf: &[u8]) -> Result<usize, IoError> {
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);
let mut guard = self.inner.write().await;
let mut pos_guard = self.pos.lock().await;
let pos = *pos_guard;
Expand All @@ -180,12 +182,10 @@ impl ObjectInterface for RamFileInterface {
guard.data.resize(pos + buf.len(), 0);
guard.attr.st_size = guard.data.len().try_into().unwrap();
}
guard.attr.st_atime = microseconds / 1_000_000;
guard.attr.st_atime_nsec = (microseconds % 1_000_000) * 1000;
guard.attr.st_mtime = guard.attr.st_atime;
guard.attr.st_mtime_nsec = guard.attr.st_atime_nsec;
guard.attr.st_ctime = guard.attr.st_atime;
guard.attr.st_ctime_nsec = guard.attr.st_atime_nsec;

guard.attr.st_atim = t;
guard.attr.st_mtim = t;
guard.attr.st_ctim = t;

guard.data[pos..pos + buf.len()].clone_from_slice(buf);
*pos_guard = pos + buf.len();
Expand Down Expand Up @@ -245,15 +245,13 @@ impl VfsNode for RomFile {
impl RomFile {
pub unsafe fn new(ptr: *const u8, length: usize, mode: AccessPermission) -> Self {
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);
let attr = FileAttr {
st_size: length.try_into().unwrap(),
st_mode: mode | AccessPermission::S_IFREG,
st_atime: microseconds / 1_000_000,
st_atime_nsec: (microseconds % 1_000_000) * 1000,
st_mtime: microseconds / 1_000_000,
st_mtime_nsec: (microseconds % 1_000_000) * 1000,
st_ctime: microseconds / 1_000_000,
st_ctime_nsec: (microseconds % 1_000_000) * 1000,
st_atim: t,
st_mtim: t,
st_ctim: t,
..Default::default()
};

Expand Down Expand Up @@ -301,14 +299,12 @@ impl VfsNode for RamFile {
impl RamFile {
pub fn new(mode: AccessPermission) -> Self {
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);
let attr = FileAttr {
st_mode: mode | AccessPermission::S_IFREG,
st_atime: microseconds / 1_000_000,
st_atime_nsec: (microseconds % 1_000_000) * 1000,
st_mtime: microseconds / 1_000_000,
st_mtime_nsec: (microseconds % 1_000_000) * 1000,
st_ctime: microseconds / 1_000_000,
st_ctime_nsec: (microseconds % 1_000_000) * 1000,
st_atim: t,
st_mtim: t,
st_ctim: t,
..Default::default()
};

Expand All @@ -328,17 +324,15 @@ pub(crate) struct MemDirectory {
impl MemDirectory {
pub fn new(mode: AccessPermission) -> Self {
let microseconds = arch::kernel::systemtime::now_micros();
let t = timespec::from_usec(microseconds as i64);

Self {
inner: Arc::new(RwLock::new(BTreeMap::new())),
attr: FileAttr {
st_mode: mode | AccessPermission::S_IFDIR,
st_atime: microseconds / 1_000_000,
st_atime_nsec: (microseconds % 1_000_000) * 1000,
st_mtime: microseconds / 1_000_000,
st_mtime_nsec: (microseconds % 1_000_000) * 1000,
st_ctime: microseconds / 1_000_000,
st_ctime_nsec: (microseconds % 1_000_000) * 1000,
st_atim: t,
st_mtim: t,
st_ctim: t,
..Default::default()
},
}
Expand Down
17 changes: 5 additions & 12 deletions src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,11 @@ pub struct FileAttr {
/// size in blocks
pub st_blocks: i64,
/// time of last access
pub st_atime: u64,
pub st_atime_nsec: u64,
pub st_atim: timespec,
/// time of last modification
pub st_mtime: u64,
pub st_mtime_nsec: u64,
pub st_mtim: timespec,
/// time of last status change
pub st_ctime: u64,
pub st_ctime_nsec: u64,
pub st_ctim: timespec,
}

#[derive(Debug, FromPrimitive, ToPrimitive)]
Expand Down Expand Up @@ -414,16 +411,12 @@ impl Metadata {

/// Returns the last modification time listed in this metadata.
pub fn modified(&self) -> Result<SystemTime, IoError> {
Ok(SystemTime::from(timespec::from_usec(
self.0.st_mtime * 1_000_000 + self.0.st_mtime_nsec / 1000,
)))
Ok(SystemTime::from(self.0.st_mtim))
}

/// Returns the last modification time listed in this metadata.
pub fn accessed(&self) -> Result<SystemTime, IoError> {
Ok(SystemTime::from(timespec::from_usec(
self.0.st_atime * 1_000_000 + self.0.st_atime_nsec / 1000,
)))
Ok(SystemTime::from(self.0.st_atim))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/syscalls/futex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub unsafe extern "C" fn sys_futex_wait(
None
} else {
match unsafe { timeout.read().into_usec() } {
t @ Some(_) => t,
None => return -EINVAL,
Some(usec) if usec >= 0 => Some(usec as u64),
_ => return -EINVAL,
}
};
let flags = match Flags::from_bits(flags) {
Expand Down
6 changes: 3 additions & 3 deletions src/syscalls/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ pub unsafe extern "C" fn sys_clock_gettime(clock_id: clockid_t, tp: *mut timespe

match clock_id {
CLOCK_REALTIME => {
*result = timespec::from_usec(arch::kernel::systemtime::now_micros());
*result = timespec::from_usec(arch::kernel::systemtime::now_micros() as i64);
0
}
CLOCK_MONOTONIC => {
*result = timespec::from_usec(arch::processor::get_timer_ticks());
*result = timespec::from_usec(arch::processor::get_timer_ticks() as i64);
0
}
_ => {
Expand Down Expand Up @@ -143,7 +143,7 @@ pub unsafe extern "C" fn sys_gettimeofday(tp: *mut timeval, tz: usize) -> i32 {
// Return the current time based on the wallclock time when we were booted up
// plus the current timer ticks.
let microseconds = arch::kernel::systemtime::now_micros();
*result = timeval::from_usec(microseconds);
*result = timeval::from_usec(microseconds as i64);
}

if tz > 0 {
Expand Down
40 changes: 21 additions & 19 deletions src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use crate::arch;
#[allow(non_camel_case_types)]
pub type time_t = i64;
#[allow(non_camel_case_types)]
pub type suseconds_t = u32;
pub type useconds_t = u32;
#[allow(non_camel_case_types)]
pub type suseconds_t = i32;

/// Represent the number of seconds and microseconds since
/// the Epoch (1970-01-01 00:00:00 +0000 (UTC))
Expand All @@ -17,18 +19,17 @@ pub struct timeval {
}

impl timeval {
pub fn from_usec(microseconds: u64) -> Self {
pub fn from_usec(microseconds: i64) -> Self {
Self {
tv_sec: (microseconds / 1_000_000) as i64,
tv_usec: (microseconds % 1_000_000) as u32,
tv_sec: (microseconds / 1_000_000),
tv_usec: (microseconds % 1_000_000) as i32,
}
}

pub fn into_usec(&self) -> Option<u64> {
u64::try_from(self.tv_sec)
.ok()
.and_then(|secs| secs.checked_mul(1_000_000))
.and_then(|millions| millions.checked_add(u64::from(self.tv_usec)))
pub fn into_usec(&self) -> Option<i64> {
self.tv_sec
.checked_mul(1_000_000)
.and_then(|usec| usec.checked_add(self.tv_usec.into()))
}
}

Expand All @@ -47,22 +48,21 @@ pub struct timespec {
/// seconds
pub tv_sec: time_t,
/// nanoseconds
pub tv_nsec: u32,
pub tv_nsec: i32,
}

impl timespec {
pub fn from_usec(microseconds: u64) -> Self {
pub fn from_usec(microseconds: i64) -> Self {
Self {
tv_sec: (microseconds / 1_000_000) as i64,
tv_nsec: ((microseconds % 1_000_000) * 1000) as u32,
tv_sec: (microseconds / 1_000_000),
tv_nsec: ((microseconds % 1_000_000) * 1000) as i32,
}
}

pub fn into_usec(&self) -> Option<u64> {
u64::try_from(self.tv_sec)
.ok()
.and_then(|secs| secs.checked_mul(1_000_000))
.and_then(|millions| millions.checked_add(u64::from(self.tv_nsec) / 1000))
pub fn into_usec(&self) -> Option<i64> {
self.tv_sec
.checked_mul(1_000_000)
.and_then(|usec| usec.checked_add((self.tv_nsec / 1000).into()))
}
}

Expand All @@ -72,7 +72,9 @@ pub struct SystemTime(timespec);
impl SystemTime {
/// Returns the system time corresponding to "now".
pub fn now() -> Self {
Self(timespec::from_usec(arch::kernel::systemtime::now_micros()))
Self(timespec::from_usec(
arch::kernel::systemtime::now_micros() as i64
))
}
}

Expand Down

0 comments on commit 5764200

Please sign in to comment.