|  | /* | 
|  | * Copyright 2013 Google Inc. | 
|  | */ | 
|  | //#define DEBUG | 
|  | #include <setjmp.h> | 
|  | #include <slab.h> | 
|  | #include <kmalloc.h> | 
|  | #include <kref.h> | 
|  | #include <string.h> | 
|  | #include <stdio.h> | 
|  | #include <assert.h> | 
|  | #include <error.h> | 
|  | #include <cpio.h> | 
|  | #include <pmap.h> | 
|  | #include <smp.h> | 
|  | #include <err.h> | 
|  |  | 
|  | /* General idea: if we're at the base for this func (base of ERRSTACK in the | 
|  | * scope where ERRSTACK and waserror are used), we need to find and save the | 
|  | * previous errbuf, so we know how to pop back. | 
|  | * | 
|  | * The main goal of this is to track and advertise (via pcpui) the errbuf that | 
|  | * should be jumped to next (when we call error()).  Note that the caller of | 
|  | * this (waserror()) will fill the jumpbuf shortly with its context. | 
|  | * | 
|  | * When we enter, curindex points to the slot we should use.  First time, it is | 
|  | * 0, and we'll set cur_eb to slot 0.  When we leave, curindex is set to the | 
|  | * next free slot. */ | 
|  | struct errbuf *errpush(struct errbuf *errstack, int stacksize, int *curindex, | 
|  | struct errbuf **prev_errbuf) | 
|  | { | 
|  | struct errbuf *cbuf; | 
|  |  | 
|  | printd("pushe %p %d %dp\n", errstack, stacksize, *curindex); | 
|  | if (*curindex == 0) | 
|  | *prev_errbuf = get_cur_errbuf(); | 
|  |  | 
|  | if (*curindex >= stacksize) | 
|  | panic("Error stack overflow"); | 
|  |  | 
|  | cbuf = &errstack[*curindex]; | 
|  | set_cur_errbuf(cbuf); | 
|  | (*curindex)++; | 
|  |  | 
|  | return cbuf; | 
|  | } | 
|  |  | 
|  | /* Undo the work of errpush, and advertise the new errbuf used by error() calls. | 
|  | * We only need to be tricky when we reached the beginning of the stack and need | 
|  | * to check the prev_errbuf from a previous ERRSTACK/function. | 
|  | * | 
|  | * When we enter, curindex is the slot of the next *free* errstack (the one we'd | 
|  | * push into if we were pushing.  When we leave, it will be decreased by one, | 
|  | * and will still point to the next free errstack (the one we are popping). | 
|  | */ | 
|  | struct errbuf *errpop(struct errbuf *errstack, int stacksize, int *curindex, | 
|  | struct errbuf *prev_errbuf) | 
|  | { | 
|  | struct errbuf *cbuf; | 
|  |  | 
|  | printd("pope %p %d %d\n", errstack, stacksize, *curindex); | 
|  | /* curindex now points to the slot we are popping*/ | 
|  | *curindex = *curindex - 1; | 
|  | /* We still need to advertise the previous slot, which is one back from | 
|  | * curindex.  If curindex is 0, that means the next free slot is the | 
|  | * first of our errstack.  In this case, we need to advertise the prev. | 
|  | */ | 
|  | if (*curindex < 0) | 
|  | panic("Error stack underflow"); | 
|  |  | 
|  | cbuf = (*curindex == 0) ? prev_errbuf: &errstack[*curindex - 1]; | 
|  | set_cur_errbuf(cbuf); | 
|  |  | 
|  | return cbuf; | 
|  | } |