a different approach to panic. for details on the new rules see the already-appled patch to panic(9nix). the idea here is to *never* hang a machine. it's too annoying. Reference: /n/atom/patch/applied2013/panicreliable Date: Sun Dec 29 16:15:51 CET 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/port/edf.c Sun Dec 29 16:15:32 2013 +++ /sys/src/nix/port/edf.c Sun Dec 29 16:15:33 2013 @@ -131,7 +131,6 @@ deadlineintr(Ureg*, Timer *t) { /* Proc reached deadline */ - extern int panicking; Proc *p; if(panicking || active.exiting) @@ -206,7 +205,6 @@ releaseintr(Ureg*, Timer *t) { Proc *p; - extern int panicking; Sched *sch; Schedq *rq; --- /sys/src/nix/port/rdb.c Sun Dec 29 16:15:34 2013 +++ /sys/src/nix/port/rdb.c Sun Dec 29 16:15:35 2013 @@ -59,7 +59,7 @@ uchar *a; char *p, *req; - delconsdevs(); /* turn off serial console and kprint */ + synccons(); // scrprint("Plan 9 debugger\n"); iprint("Edebugger reset\n"); for(;;){ --- /sys/src/nix/port/portfns.h Sun Dec 29 16:15:36 2013 +++ /sys/src/nix/port/portfns.h Sun Dec 29 16:15:36 2013 @@ -51,7 +51,6 @@ uintptr dbgpc(Proc*); int decref(Ref*); void delay(int); -void delconsdevs(void); Proc* dequeueproc(Sched*, Schedq*, Proc*); Chan* devattach(int, char*); Block* devbread(Chan*, long, vlong); @@ -342,6 +341,7 @@ void startwaitstats(int); int swapcount(ulong); void swapinit(void); +void synccons(void); void syscallfmt(int, va_list list); void sysretfmt(int, va_list, Ar0*, uvlong, uvlong); void* sysexecregs(uintptr, uint, uint); --- /sys/src/nix/port/portdat.h Sun Dec 29 16:15:38 2013 +++ /sys/src/nix/port/portdat.h Sun Dec 29 16:15:39 2013 @@ -995,8 +995,9 @@ * console flags &c */ enum { - Ciprint = 2, /* call this fn from iprint */ - Cntorn = 4, /* change \n to \r\n */ + Csync = 1<<0, /* use in synchronous mode (e.g. panic) */ + Ciprint = 1<<1, /* call this fn from iprint */ + Cntorn = 1<<2, /* change \n to \r\n */ }; /* @@ -1050,13 +1051,13 @@ extern Ref noteidalloc; extern int nphysseg; extern int nsyscall; +extern int panicking; extern Pgalloc pga; extern Physseg physseg[]; extern Procalloc procalloc; extern uint qiomaxatomic; extern Sched run[]; extern char* statename[]; -extern char* sysname; extern Lockstats lockstats; extern QLockstats qlockstats; extern Waitstats waitstats; --- /sys/src/nix/port/devuart.c Sun Dec 29 16:15:40 2013 +++ /sys/src/nix/port/devuart.c Sun Dec 29 16:15:41 2013 @@ -433,7 +433,7 @@ } p->putc = kbdcr2nl; addkbdq(p->iq, -1); - addconsdev(p->oq, uartputs, 2, 0); + addconsdev(p->oq, uartputs, 2, Csync|Ciprint|Cntorn); // consuart = p; p->opens++; p->console = 1; --- /sys/src/nix/port/devcons.c Sun Dec 29 16:15:43 2013 +++ /sys/src/nix/port/devcons.c Sun Dec 29 16:15:44 2013 @@ -30,13 +30,14 @@ static Lock consdevslock; static int nconsdevs = 3; -static Consdev consdevs[Nconsdevs] = /* keep this order */ +static Consdev consdevs[Nconsdevs] = { - {nil, nil, kmesgputs, 0}, /* kmesg */ - {nil, nil, kprintputs, Ciprint}, /* kprint */ - {nil, nil, uartputs, Ciprint|Cntorn}, /* serial */ + {nil, nil, kmesgputs, 0, }, /* kmesg */ + {nil, nil, kprintputs, Csync|Ciprint, }, /* kprint */ + {nil, nil, uartputs, Csync|Ciprint|Cntorn, }, /* serial (botch! must be 2d) */ }; +static int syncprint; static int nkbdqs; static int nkbdprocs; static Queue* kbdqs[Nconsdevs]; @@ -75,8 +76,8 @@ .ie = kbd.istage + sizeof(kbd.istage), }; -char *sysname; -vlong fasthz; +static char *sysname; +static vlong fasthz; static void seedrand(void); static int readtime(ulong, char*, int); @@ -112,12 +113,11 @@ Consdev *c; ilock(&consdevslock); - if(i < 0) - i = nconsdevs; - else - flags |= consdevs[i].flags; - if(nconsdevs == Nconsdevs) + if(i < 0){ + if(nconsdevs == Nconsdevs) panic("Nconsdevs too small"); + i = nconsdevs; + } c = &consdevs[i]; c->flags = flags; c->q = q; @@ -128,13 +128,6 @@ return i; } -void -delconsdevs(void) -{ - nconsdevs = 2; /* throw away serial consoles and kprint */ - consdevs[1].q = nil; -} - static void conskbdqproc(void *a) { @@ -275,14 +268,25 @@ Chan *cc; Queue *q; + if(syncprint){ + usewrite = 0; + if((c->flags & Csync) == 0) + return; + } + + if(!islo()) + usewrite = 0; + if(usewrite == 0 && (c->flags & Ciprint) == 0) + return; + if((cc = c->c) != nil && usewrite) cc->dev->write(cc, s, n, 0); - else if((q = c->q) != nil && !qisclosed(q)) + else if(!syncprint && (q = c->q) != nil && !qisclosed(q)){ if(usewrite) qwrite(q, s, n); else qiwrite(q, s, n); - else if(c->fn != nil) + }else c->fn(s, n); } @@ -299,9 +303,6 @@ char *s, *t; int i, len, m; - if(!islo()) - usewrite = 0; - for(i = 0; i < nconsdevs; i++){ c = &consdevs[i]; len = n; @@ -372,7 +373,7 @@ iprint(char *fmt, ...) { Mpl pl; - int i, n, locked; + int n, locked; va_list arg; char buf[PRINTSIZE]; @@ -381,13 +382,7 @@ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); locked = iprintcanlock(&iprintlock); - for(i = 0; i < nconsdevs; i++) - if((consdevs[i].flags&Ciprint) != 0){ - if(consdevs[i].q != nil) - qiwrite(consdevs[i].q, buf, n); - else - consdevs[i].fn(buf, n); - } + putstrn0(buf, n, 0); if(locked) unlock(&iprintlock); splx(pl); @@ -395,35 +390,38 @@ return n; } +void +synccons(void) +{ + syncprint = 1; +/* prflush(); */ +} + #pragma profile 0 void panic(char *fmt, ...) { - int n; - Mpl pl; + char *p, buf[PRINTSIZE]; va_list arg; - char buf[PRINTSIZE]; - - consdevs[1].q = nil; /* don't try to write to /dev/kprint */ + static pmno = -1; - if(panicking) - for(;;); - panicking = 1; + if(ainc(&panicking)>1){ + if(m->machno == pmno) + archreset(); + ndnr(); + } + pmno = m->machno; + synccons(); - pl = splhi(); - seprint(buf, buf+sizeof buf, "panic: cpu%d: ", m->machno); + splhi(); /* never to release */ + p = seprint(buf, buf+sizeof buf, "panic: cpu%d: ", m->machno); va_start(arg, fmt); - n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; + vseprint(p, buf+sizeof(buf), fmt, arg); va_end(arg); iprint("%s\n", buf); - if(consdebug) - (*consdebug)(); - splx(pl); - prflush(); - buf[n] = '\n'; - putstrn(buf, n+1); + if(consdebug != nil) + consdebug(); dumpstack(); - delay(1000); /* give time to consoles */ exit(1); }