RustForge

foundry

Foundry OS: the operating system built on the Rustbelt kernel

authorEdward <edward@localhost>2026-10-31 17:22:26 -0700
commit85f5cd4654028d87fb6ef32f915a0073f0064d2d
parente6eb9917e47dda5cf57b32256ee0c85032c1c600
treebrowse files at this commit
Stage 18 prep: fixes from Clarke's 0.17.0 review

- timer_getoverrun / si_overrun: while a POSIX timer's signal is still
  pending, further expirations add to the overrun count (they used to
  overwrite it). The count is latched when the signal is delivered:
  getoverrun reports the last delivered signal's overrun (0 before the
  first delivery), and counting starts over for the next one.
- timerd starts at boot, so the first timer no longer costs 16 frames
  after the headless report's "before" snapshot (report is flat again).
- coretest statfs: stat/lstat/fstat of mount points (/tmp, /dev,
  /mnt/disk1) report the mounted fs's st_dev (and ext2's root ino 2).
  These already passed: the probe's "/tmp has /'s st_dev" came from
  printing st.st_dev in the same printf call as a later stat("/", &st)
  argument (C evaluates arguments in unspecified order).
Mcoretest.rs+38 -0

1 file changed, 38 insertions, 0 deletions

@@ -361,6 +361,20 @@ fn statfs(c: &mut Checks) {     close(w);     // st_dev tells file systems apart.     c.check(st("/tmp").dev != st("/mnt/disk1").dev && st("/mnt/disk1/").dev == st("/mnt/disk1/lost+found").dev, "st_dev: one per file system");+    // Stage 18 fix check (Clarke): a mount point itself reports the+    // *mounted* file system's st_dev and root inode, not the directory it+    // covers. find -xdev, du -x and cp -x compare st_dev with this.+    write_file("/tmp/devchk", b"x");+    c.check(st("/tmp").dev == st("/tmp/devchk").dev && st("/tmp").dev != st("/").dev, "stat(\"/tmp\"): the mounted ramfs's st_dev, not /'s");+    c.check(st("/dev").dev == st("/dev/null").dev && st("/dev").dev != st("/").dev, "stat(\"/dev\"): devfs's st_dev");+    c.check(st("/mnt/disk1").dev == st("/mnt/disk1/lost+found").dev && st("/mnt/disk1").ino == 2, "stat(\"/mnt/disk1\"): ext2's st_dev and its root inode (2)");+    let mut ls = Stat::default();+    c.check(lstat("/tmp", &mut ls) == 0 && ls.dev == st("/tmp/devchk").dev, "lstat of a mount point: the mounted fs's st_dev too");+    let fd = open("/mnt/disk1", O_RDONLY | O_DIRECTORY);+    let mut fs_ = Stat::default();+    c.check(fstat(fd, &mut fs_) == 0 && fs_.dev == st("/mnt/disk1/lost+found").dev && fs_.ino == 2, "fstat of an fd opened on a mount point: same");+    close(fd);+    unlink("/tmp/devchk");     // statx     write_file("/tmp/sx.txt", b"twelve bytes");     let mut sx = [0u8; 256];@@ -535,6 +549,7 @@ fn sockets(c: &mut Checks) { static ALRM: AtomicI64 = AtomicI64::new(0); static TCODE: AtomicI64 = AtomicI64::new(0); static TVAL: AtomicU64 = AtomicU64::new(0);+static TOVR: AtomicI64 = AtomicI64::new(-1);  extern "C" fn on_alarm(_sig: i32) {     ALRM.fetch_add(1, Ordering::SeqCst);@@ -544,6 +559,7 @@ extern "C" fn on_timer(_sig: i32, info: *const SigInfo, _ctx: *mut u8) {     unsafe {         TCODE.store((*info).code as i64, Ordering::SeqCst);         TVAL.store(*((info as *const u8).add(24) as *const u64), Ordering::SeqCst);+        TOVR.store(*((info as *const u8).add(20) as *const i32) as i64, Ordering::SeqCst); // si_overrun     }     ALRM.fetch_add(1, Ordering::SeqCst); }@@ -638,6 +654,28 @@ fn timers(c: &mut Checks) {     c.check(old[1] == 50_000_000, "disarming returns the old interval");     c.check(syscall3(SYS_TIMER_DELETE, id as u64, 0, 0) == 0, "timer_delete");     c.check(syscall3(SYS_TIMER_DELETE, id as u64, 0, 0) == -EINVAL, "timer_delete again: EINVAL");+    // Overruns (stage 18 fix, found by Clarke): a 20 ms timer whose signal+    // is blocked for 0.5 s expires ~25 times but sends one signal; the+    // other ~24 add up as overruns. timer_getoverrun reports the count of+    // the last *delivered* signal: 0 while it is still pending.+    ALRM.store(0, Ordering::SeqCst);+    TOVR.store(-1, Ordering::SeqCst);+    let r = syscall3(SYS_TIMER_CREATE, 1, sev.as_ptr() as u64, &mut id as *mut i32 as u64);+    let old_mask = sigprocmask(SIG_BLOCK, sigbit(SIGUSR1)) as u64;+    let spec = [0u64, 20_000_000, 0, 20_000_000]; // every 20 ms+    syscall6(SYS_TIMER_SETTIME, id as u64, 0, spec.as_ptr() as u64, 0, 0, 0);+    sleep_through(500);+    c.check(r == 0 && syscall3(SYS_TIMER_GETOVERRUN, id as u64, 0, 0) == 0, "overrun: 0 before the first signal is delivered");+    sigprocmask(SIG_SETMASK, old_mask); // delivered now+    let first = TOVR.load(Ordering::SeqCst);+    let got = syscall3(SYS_TIMER_GETOVERRUN, id as u64, 0, 0);+    c.check(ALRM.load(Ordering::SeqCst) == 1 && (18..=30).contains(&first), &format!("blocked 0.5 s: one signal, si_overrun {} (Linux: ~24)", first));+    c.check(got == first, &format!("timer_getoverrun = the delivered signal's si_overrun ({})", got));+    c.check(wait_for(2, 1000), "unblocked: the next signal comes");+    let next = TOVR.load(Ordering::SeqCst);+    // (Not 0: timerd and signal delivery both work in ~55 ms ticks.)+    c.check((0..=10).contains(&next), &format!("...with a fresh count ({}), not the old one added", next));+    syscall3(SYS_TIMER_DELETE, id as u64, 0, 0);     // SIGEV_NONE: nothing is sent, the time just runs down.     sev[1] = 1u64 << 32; // notify = SIGEV_NONE     syscall3(SYS_TIMER_CREATE, 0, sev.as_ptr() as u64, &mut id as *mut i32 as u64);