e113e13723
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
126 lines
4.1 KiB
Diff
126 lines
4.1 KiB
Diff
diff -ruN a/src/header/mod.rs b/src/header/mod.rs
|
|
--- a/src/header/mod.rs 2026-04-15 09:58:03.811510680 +0100
|
|
+++ b/src/header/mod.rs 2026-04-15 09:59:40.902089070 +0100
|
|
@@ -103,6 +103,7 @@
|
|
pub mod sys_stat;
|
|
pub mod sys_statvfs;
|
|
pub mod sys_time;
|
|
+pub mod sys_timerfd;
|
|
#[deprecated]
|
|
pub mod sys_timeb;
|
|
//pub mod sys_times;
|
|
diff -ruN a/src/header/sys_timerfd/cbindgen.toml b/src/header/sys_timerfd/cbindgen.toml
|
|
--- a/src/header/sys_timerfd/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
|
+++ b/src/header/sys_timerfd/cbindgen.toml 2026-04-15 09:59:40.902120449 +0100
|
|
@@ -0,0 +1,12 @@
|
|
+sys_includes = ["time.h"]
|
|
+include_guard = "_SYS_TIMERFD_H"
|
|
+language = "C"
|
|
+style = "Tag"
|
|
+no_includes = true
|
|
+cpp_compat = true
|
|
+
|
|
+[enum]
|
|
+prefix_with_name = true
|
|
+
|
|
+[export.rename]
|
|
+"itimerspec" = "struct itimerspec"
|
|
diff -ruN a/src/header/sys_timerfd/mod.rs b/src/header/sys_timerfd/mod.rs
|
|
--- a/src/header/sys_timerfd/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
|
+++ b/src/header/sys_timerfd/mod.rs 2026-04-15 09:59:40.902160103 +0100
|
|
@@ -0,0 +1,94 @@
|
|
+//! `sys/timerfd.h` implementation.
|
|
+//!
|
|
+//! Non-POSIX, see <https://man7.org/linux/man-pages/man2/timerfd_create.2.html>.
|
|
+
|
|
+use alloc::format;
|
|
+use core::{mem, slice};
|
|
+
|
|
+use crate::{
|
|
+ c_str::{CStr, CString},
|
|
+ error::{Errno, ResultExt},
|
|
+ header::{
|
|
+ bits_timespec::timespec,
|
|
+ errno::{EFAULT, EINVAL, EIO},
|
|
+ fcntl::{O_CLOEXEC, O_NONBLOCK, O_RDWR},
|
|
+ },
|
|
+ platform::{
|
|
+ Pal, Sys,
|
|
+ types::{c_int, clockid_t},
|
|
+ },
|
|
+};
|
|
+
|
|
+pub use crate::header::time::itimerspec;
|
|
+
|
|
+pub const TFD_CLOEXEC: c_int = 0x80000;
|
|
+pub const TFD_NONBLOCK: c_int = 0x800;
|
|
+pub const TFD_TIMER_ABSTIME: c_int = 0x1;
|
|
+pub const TFD_TIMER_CANCEL_ON_SET: c_int = 0x2;
|
|
+
|
|
+fn read_exact(fd: c_int, buf: &mut [u8]) -> Result<(), Errno> {
|
|
+ match Sys::read(fd, buf)? {
|
|
+ n if n == buf.len() => Ok(()),
|
|
+ _ => Err(Errno(EIO)),
|
|
+ }
|
|
+}
|
|
+
|
|
+fn write_exact(fd: c_int, buf: &[u8]) -> Result<(), Errno> {
|
|
+ match Sys::write(fd, buf)? {
|
|
+ n if n == buf.len() => Ok(()),
|
|
+ _ => Err(Errno(EIO)),
|
|
+ }
|
|
+}
|
|
+
|
|
+#[unsafe(no_mangle)]
|
|
+pub extern "C" fn timerfd_create(clockid: clockid_t, flags: c_int) -> c_int {
|
|
+ let supported = TFD_CLOEXEC | TFD_NONBLOCK;
|
|
+ if flags & !supported != 0 {
|
|
+ return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno();
|
|
+ }
|
|
+
|
|
+ let mut oflag = O_RDWR;
|
|
+ if flags & TFD_CLOEXEC == TFD_CLOEXEC {
|
|
+ oflag |= O_CLOEXEC;
|
|
+ }
|
|
+ if flags & TFD_NONBLOCK == TFD_NONBLOCK {
|
|
+ oflag |= O_NONBLOCK;
|
|
+ }
|
|
+
|
|
+ let path = match CString::new(format!("/scheme/time/{clockid}")) {
|
|
+ Ok(path) => path,
|
|
+ Err(_) => return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno(),
|
|
+ };
|
|
+ Sys::open(CStr::borrow(&path), oflag, 0).or_minus_one_errno()
|
|
+}
|
|
+
|
|
+#[unsafe(no_mangle)]
|
|
+pub unsafe extern "C" fn timerfd_settime(fd: c_int, flags: c_int, new: *const itimerspec, old: *mut itimerspec) -> c_int {
|
|
+ let supported = TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET;
|
|
+ if flags & !supported != 0 {
|
|
+ return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno();
|
|
+ }
|
|
+ if flags & TFD_TIMER_CANCEL_ON_SET != 0 && flags & TFD_TIMER_ABSTIME == 0 {
|
|
+ return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno();
|
|
+ }
|
|
+ if new.is_null() {
|
|
+ return Err::<c_int, _>(Errno(EFAULT)).or_minus_one_errno();
|
|
+ }
|
|
+ if !old.is_null() && unsafe { timerfd_gettime(fd, old) } < 0 {
|
|
+ return -1;
|
|
+ }
|
|
+ let spec = unsafe { &*new };
|
|
+ let buf = unsafe { slice::from_raw_parts((&raw const spec.it_value).cast::<u8>(), mem::size_of::<timespec>()) };
|
|
+ write_exact(fd, buf).map(|()| 0).or_minus_one_errno()
|
|
+}
|
|
+
|
|
+#[unsafe(no_mangle)]
|
|
+pub unsafe extern "C" fn timerfd_gettime(fd: c_int, curr: *mut itimerspec) -> c_int {
|
|
+ if curr.is_null() {
|
|
+ return Err::<c_int, _>(Errno(EFAULT)).or_minus_one_errno();
|
|
+ }
|
|
+ let curr = unsafe { &mut *curr };
|
|
+ curr.it_interval = timespec::default();
|
|
+ let buf = unsafe { slice::from_raw_parts_mut((&raw mut curr.it_value).cast::<u8>(), mem::size_of::<timespec>()) };
|
|
+ read_exact(fd, buf).map(|()| 0).or_minus_one_errno()
|
|
+}
|