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