// 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 #include #include 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; }