foundry
Foundry OS: the operating system built on the Rustbelt kernel
| author | Edward <edward@localhost> | 2026-10-31 17:22:26 -0700 |
|---|---|---|
| commit | 85f5cd4654028d87fb6ef32f915a0073f0064d2d | |
| parent | e6eb9917e47dda5cf57b32256ee0c85032c1c600 | |
| tree | browse 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).| M | coretest.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);