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