65816-llvm-mos/demos/gnoWaitpidTimesProbe.c
2026-07-07 18:33:48 -05:00

59 lines
2.4 KiB
C

// waitpid + times regression for GNO/ME. Forks a leaf child that _exit(37)s,
// then the parent reaps it with waitpid(pid, &st, 0) -- verifying the pure-C
// waitpid loop returns the exact child pid and the real exit status -- and
// finally calls times() and checks the deterministic fields the GNO kernel
// zero-fills (return value, tms_stime, tms_cstime), a crash-free sanity marker.
//
// GNO fork is a thread-spawn: the child begins at child() on a fresh stack/DP,
// so child() is a LEAF using only absolute-long stores + _exit (no DP scratch).
// Bank-2 absolute markers (DBR-independent), per the gnoForkWaitProbe convention.
// 0x025000 C0DE reached end (no hang in waitpid/times)
// 0x025010 C41D child was scheduled + ran
// 0x025014 0025 WEXITSTATUS == 37 (status propagated through waitpid)
// 0x025016 0001 waitpid reaped the same pid fork() returned
// 0x025018 0001 times() sanity: ret==0 && tms_stime==0 && tms_cstime==0
#include <stdint.h>
#include <sys/wait.h>
#include <sys/times.h>
extern int fork(void *subr); // GNO thread-spawn: subr = (void *)&childFn
extern __attribute__((noreturn)) void _exit(int status);
extern int waitpid(int pid, int *status, int options);
extern clock_t times(struct tms *buf);
#define M(a) (*(volatile uint16_t *)(a))
static void child(void) {
M(0x025010UL) = 0xC41D; // child was scheduled + entered child()
_exit(37); // exit code 37 -> status word 0x2500
}
int main(void) {
M(0x025000UL) = 0x0000;
int pid = fork((void *)child);
if (pid <= 0) {
M(0x025016UL) = 0xDEAD; // fork failed / returned no child
M(0x025000UL) = 0xC0DE;
for (volatile unsigned long j = 0; j < 300000UL; j++) {
}
return 0;
}
int st = 0;
int w = waitpid(pid, &st, 0); // pure-C loop over wait() until pid reaped
M(0x025014UL) = WIFEXITED(st) ? (uint16_t)WEXITSTATUS(st) : 0xEEEE; // == 0x0025
M(0x025016UL) = (w == pid) ? 0x0001 : 0xDEAD; // pid round-trip
struct tms tb;
tb.tms_stime = 0xFFFFFFFFUL; // poison; kernel must overwrite with 0
tb.tms_cstime = 0xFFFFFFFFUL;
clock_t rc = times(&tb);
uint16_t timesOk = (rc == 0 && tb.tms_stime == 0 && tb.tms_cstime == 0) ? 0x0001 : 0xDEAD;
M(0x025018UL) = timesOk;
M(0x025000UL) = 0xC0DE; // reached end
for (volatile unsigned long j = 0; j < 300000UL; j++) {
}
return 0;
}