--- /n/sources/plan9/sys/src/9k/port/page.c Mon Jun 22 18:18:15 2026 +++ /sys/src/9k/port/page.c Sun Oct 25 00:00:00 2026 @@ -316,6 +316,8 @@ static void pagewait(uintptr va, int color) { + static uint killticks; + qlock(&palloc.pwait); /* Hold memory requesters here */ while(waserror()) /* Ignore interrupts */ @@ -331,6 +333,12 @@ pagereclaim(highwater/2); tsleep(&palloc.r, ispages, 0, 1000); + if(!ispages(nil) && sys->ticks - killticks >= ms2tk(5000)){ + killbig("out of memory"); + freebroken(); + wakebig(); + killticks = sys->ticks; + } poperror(); qunlock(&palloc.pwait); --- /n/sources/plan9/sys/src/9k/port/portfns.h Sun Jun 28 00:00:00 2026 +++ /sys/src/9k/port/portfns.h Sun Oct 25 00:00:00 2026 @@ -349,6 +349,7 @@ char* validnamedup(char*, int); void validstat(uchar*, usize); void* vmemchr(void*, int, int); +void wakebig(void); Proc* wakeup(Rendez*); int walk(Chan**, char**, int, int, int*); void wlock(RWlock*); --- /n/sources/plan9/sys/src/9k/port/proc.c Fri Aug 7 00:00:00 2026 +++ /sys/src/9k/port/proc.c Sun Oct 25 00:00:00 2026 @@ -1503,6 +1503,25 @@ psdecref(kp); } +/* + * wake the processes killbig marked, so that those + * asleep in the kernel exit too + */ +void +wakebig(void) +{ + int x; + Proc *p; + + for(x = 0; (p = psincref(x)) != nil; x++) { + if(p->state != Dead && p->procctl == Proc_exitbig && canqlock(&p->debug)){ + postnote(p, 0, "sys: killed", NExit); + qunlock(&p->debug); + } + psdecref(p); + } +} + /* * change ownership to 'new' of all processes owned by 'old'. Used when * eve changes.