Files
RedBear-OS/local/patches/relibc/P3-timerfd-impl.patch
T
vasilito f31522130f fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed
Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
2026-05-05 20:20:37 +01:00

139 lines
4.7 KiB
Diff

--- source-old/src/header/sys_timerfd/mod.rs 2026-05-03 20:55:05.750445686 +0100
+++ source-old/src/header/sys_timerfd/mod.rs 2026-04-29 20:43:18.559857138 +0100
@@ -0,0 +1,135 @@
+//! `sys/timerfd.h` implementation.
+//!
+//! Non-POSIX, see <https://man7.org/linux/man-pages/man2/timerfd_create.2.html>.
+
+use alloc::{collections::BTreeMap, format};
+use core::{mem, slice, sync::atomic::{AtomicBool, Ordering}};
+
+use crate::{
+ c_str::{CStr, CString},
+ error::{Errno, ResultExt},
+ header::{
+ bits_timespec::timespec,
+ errno::{EBADF, EFAULT, EINVAL, EIO},
+ fcntl::{O_CLOEXEC, O_NONBLOCK, O_RDWR},
+ },
+ out::Out,
+ platform::{
+ Pal, Sys,
+ types::{c_int, clockid_t},
+ },
+ sync::Mutex,
+};
+
+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;
+
+const NSEC_PER_SEC: i64 = 1_000_000_000;
+
+static MAP_INIT: AtomicBool = AtomicBool::new(false);
+static TIMERFD_CLOCKIDS: Mutex<Option<BTreeMap<c_int, clockid_t>>> = Mutex::new(None);
+
+fn with_map<R>(f: impl FnOnce(&mut BTreeMap<c_int, clockid_t>) -> R) -> R {
+ let mut guard = TIMERFD_CLOCKIDS.lock();
+ if !MAP_INIT.load(Ordering::Acquire) {
+ *guard = Some(BTreeMap::new());
+ MAP_INIT.store(true, Ordering::Release);
+ }
+ f(guard.as_mut().unwrap())
+}
+
+fn add_timespec(a: &timespec, b: &timespec) -> timespec {
+ let total_nsec = a.tv_nsec as i64 + b.tv_nsec as i64;
+ let mut sec = a.tv_sec + b.tv_sec + (total_nsec / NSEC_PER_SEC) as i64;
+ let mut nsec = (total_nsec % NSEC_PER_SEC) as i64;
+ if nsec < 0 {
+ sec -= 1;
+ nsec += NSEC_PER_SEC;
+ }
+ timespec { tv_sec: sec, tv_nsec: nsec }
+}
+
+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(),
+ };
+ let fd = Sys::open(CStr::borrow(&path), oflag, 0).or_minus_one_errno()?;
+
+ // Register the clockid for this fd so timerfd_settime can convert relative times
+ with_map(|map| { map.insert(fd, clockid); });
+
+ fd
+}
+
+#[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 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 mut value = spec.it_value;
+
+ // Convert relative time to absolute if TFD_TIMER_ABSTIME is not set
+ if flags & TFD_TIMER_ABSTIME == 0 {
+ let clockid = with_map(|map| map.get(&fd).copied()).unwrap_or(0);
+ let mut now = timespec::default();
+ if Sys::clock_gettime(clockid, Out::from_mut(&mut now)).is_err() {
+ return Err::<c_int, _>(Errno(EBADF)).or_minus_one_errno();
+ }
+ value = add_timespec(&now, &value);
+ }
+
+ let buf = unsafe { slice::from_raw_parts((&raw const 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()
+}