P9 kernel exception handling: basically, there's a small per-process stack of *very* trimmed-down jmp_buf in their task_struct. Primitives are: waserror() - analog of setjmp(), puts new element on stack. poperror() - remove from stack error(message) - analog of longjmp(); removes top element from stack and goes there. String argument is copied to task_struct. nexterror() - basically, throw the same exception again - at the next element of stack. Typical use: lock something if (waserror()) { unlock it nexterror(); } allocate something if failed error(Enomem); if (waserror()) { free it nexterror(); } do other stuff (it might also call error(), obviously) free what we'd allocated poperror(); unlock what we'd locked. poperror(); Of course, you have to stop calling nexterror() at some point. Note that it's only for process context (obviously - anybody who wants to throw exceptions in bottom half should seek professional help) and the stack is pretty shallow, so it should be used sparingly. Usual notes re cleanup in intermediate functions apply, so it's really for the code that is close to userland. Implementation is fairly trivial - for the sake of completeness that's what they do, but it's pretty much obvious from the above. Part of that code is arch-dependent (I'm quoting 386 code), part is generic; for generic stuff see port/portfns.h, port/proc.c, port/portdat.h, for 386 - pc/fns.h, pc/dat.h, pc/l.s. #define poperror() up->nerrlab-- #define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) void nexterror(void) { gotolabel(&up->errlab[--up->nerrlab]); } void error(char *err) { spllo(); assert(up->nerrlab < NERR); kstrcpy(up->errstr, err, ERRMAX); setlabel(&up->errlab[NERR-1]); nexterror(); } NERR is 64. Label errlab[NERR]; is a field in their equivalent of task_struct. P9 "up" == our "current". Label (on 386) is a pair (pc, sp). gotolabel() and setlabel() for 386 follow - BTW, they use them to do their analog of non-C part of switch_to(). TEXT gotolabel(SB), $0 MOVL label+0(FP), AX MOVL 0(AX), SP /* restore sp */ MOVL 4(AX), AX /* put return pc on the stack */ MOVL AX, 0(SP) MOVL $1, AX /* return 1 */ RET TEXT setlabel(SB), $0 MOVL label+0(FP), AX MOVL SP, 0(AX) /* store sp */ MOVL 0(SP), BX /* store return pc */ MOVL BX, 4(AX) MOVL $0, AX /* return 0 */ RET