diff options
author | Russ Cox <rsc@golang.org> | 2014-11-20 11:48:08 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-11-20 11:48:08 -0500 |
commit | 4a674f45d109048fcef7cd9f2b876e270625c8ed (patch) | |
tree | 3015eab80ef343dda34fb968843c8b2d28987f05 /src/runtime/panic.c | |
parent | fbd764146d71d8929edadc4abd51e89932742000 (diff) | |
parent | 1ac4b754e58ba42944de03808fb96210b065e4c4 (diff) | |
download | go-4a674f45d109048fcef7cd9f2b876e270625c8ed.tar.gz |
[dev.cc] all: merge default (e4ab8f908aac) into dev.cc
TBR=austin
CC=golang-codereviews
https://codereview.appspot.com/179040044
Diffstat (limited to 'src/runtime/panic.c')
-rw-r--r-- | src/runtime/panic.c | 200 |
1 files changed, 0 insertions, 200 deletions
diff --git a/src/runtime/panic.c b/src/runtime/panic.c deleted file mode 100644 index 24eb6dbfe..000000000 --- a/src/runtime/panic.c +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "arch_GOARCH.h" -#include "stack.h" -#include "malloc.h" -#include "textflag.h" - -// Code related to defer, panic and recover. - -// TODO: remove once code is moved to Go -extern Defer* runtime·newdefer(int32 siz); -extern runtime·freedefer(Defer *d); - -uint32 runtime·panicking; -static Mutex paniclk; - -void -runtime·deferproc_m(void) -{ - int32 siz; - FuncVal *fn; - uintptr argp; - uintptr callerpc; - Defer *d; - - siz = g->m->scalararg[0]; - fn = g->m->ptrarg[0]; - argp = g->m->scalararg[1]; - callerpc = g->m->scalararg[2]; - g->m->ptrarg[0] = nil; - g->m->scalararg[1] = 0; - - d = runtime·newdefer(siz); - if(d->panic != nil) - runtime·throw("deferproc: d->panic != nil after newdefer"); - d->fn = fn; - d->pc = callerpc; - d->argp = argp; - runtime·memmove(d+1, (void*)argp, siz); -} - -// Unwind the stack after a deferred function calls recover -// after a panic. Then arrange to continue running as though -// the caller of the deferred function returned normally. -void -runtime·recovery_m(G *gp) -{ - void *argp; - uintptr pc; - - // Info about defer passed in G struct. - argp = (void*)gp->sigcode0; - pc = (uintptr)gp->sigcode1; - - // d's arguments need to be in the stack. - if(argp != nil && ((uintptr)argp < gp->stack.lo || gp->stack.hi < (uintptr)argp)) { - runtime·printf("recover: %p not in [%p, %p]\n", argp, gp->stack.lo, gp->stack.hi); - runtime·throw("bad recovery"); - } - - // Make the deferproc for this d return again, - // this time returning 1. The calling function will - // jump to the standard return epilogue. - // The -2*sizeof(uintptr) makes up for the - // two extra words that are on the stack at - // each call to deferproc. - // (The pc we're returning to does pop pop - // before it tests the return value.) - // On the arm there are 2 saved LRs mixed in too. - if(thechar == '5') - gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr); - else - gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr); - gp->sched.pc = pc; - gp->sched.lr = 0; - gp->sched.ret = 1; - runtime·gogo(&gp->sched); -} - -void -runtime·startpanic_m(void) -{ - if(runtime·mheap.cachealloc.size == 0) { // very early - runtime·printf("runtime: panic before malloc heap initialized\n"); - g->m->mallocing = 1; // tell rest of panic not to try to malloc - } else if(g->m->mcache == nil) // can happen if called from signal handler or throw - g->m->mcache = runtime·allocmcache(); - switch(g->m->dying) { - case 0: - g->m->dying = 1; - if(g != nil) { - g->writebuf.array = nil; - g->writebuf.len = 0; - g->writebuf.cap = 0; - } - runtime·xadd(&runtime·panicking, 1); - runtime·lock(&paniclk); - if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0) - runtime·schedtrace(true); - runtime·freezetheworld(); - return; - case 1: - // Something failed while panicing, probably the print of the - // argument to panic(). Just print a stack trace and exit. - g->m->dying = 2; - runtime·printf("panic during panic\n"); - runtime·dopanic(0); - runtime·exit(3); - case 2: - // This is a genuine bug in the runtime, we couldn't even - // print the stack trace successfully. - g->m->dying = 3; - runtime·printf("stack trace unavailable\n"); - runtime·exit(4); - default: - // Can't even print! Just exit. - runtime·exit(5); - } -} - -void -runtime·dopanic_m(void) -{ - G *gp; - uintptr sp, pc; - static bool didothers; - bool crash; - int32 t; - - gp = g->m->ptrarg[0]; - g->m->ptrarg[0] = nil; - pc = g->m->scalararg[0]; - sp = g->m->scalararg[1]; - g->m->scalararg[1] = 0; - if(gp->sig != 0) - runtime·printf("[signal %x code=%p addr=%p pc=%p]\n", - gp->sig, gp->sigcode0, gp->sigcode1, gp->sigpc); - - if((t = runtime·gotraceback(&crash)) > 0){ - if(gp != gp->m->g0) { - runtime·printf("\n"); - runtime·goroutineheader(gp); - runtime·traceback(pc, sp, 0, gp); - } else if(t >= 2 || g->m->throwing > 0) { - runtime·printf("\nruntime stack:\n"); - runtime·traceback(pc, sp, 0, gp); - } - if(!didothers) { - didothers = true; - runtime·tracebackothers(gp); - } - } - runtime·unlock(&paniclk); - if(runtime·xadd(&runtime·panicking, -1) != 0) { - // Some other m is panicking too. - // Let it print what it needs to print. - // Wait forever without chewing up cpu. - // It will exit when it's done. - static Mutex deadlock; - runtime·lock(&deadlock); - runtime·lock(&deadlock); - } - - if(crash) - runtime·crash(); - - runtime·exit(2); -} - -#pragma textflag NOSPLIT -bool -runtime·canpanic(G *gp) -{ - M *m; - uint32 status; - - // Note that g is m->gsignal, different from gp. - // Note also that g->m can change at preemption, so m can go stale - // if this function ever makes a function call. - m = g->m; - - // Is it okay for gp to panic instead of crashing the program? - // Yes, as long as it is running Go code, not runtime code, - // and not stuck in a system call. - if(gp == nil || gp != m->curg) - return false; - if(m->locks-m->softfloat != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0) - return false; - status = runtime·readgstatus(gp); - if((status&~Gscan) != Grunning || gp->syscallsp != 0) - return false; -#ifdef GOOS_windows - if(m->libcallsp != 0) - return false; -#endif - return true; -} |