dopanic(0)
*(*int)(nil) = 0 // not reached
}
+
+//uint32 runtime·panicking;
+var paniclk mutex
+
+const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
+
+// 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.
+func recovery(gp *g) {
+ // Info about defer passed in G struct.
+ sp := gp.sigcode0
+ pc := gp.sigcode1
+
+ // d's arguments need to be in the stack.
+ if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
+ print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
+ 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.
+ gcUnwindBarriers(gp, sp)
+ gp.sched.sp = sp
+ gp.sched.pc = pc
+ gp.sched.lr = 0
+ gp.sched.ret = 1
+ gogo(&gp.sched)
+}
+
+func startpanic_m() {
+ _g_ := getg()
+ if mheap_.cachealloc.size == 0 { // very early
+ print("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 = allocmcache()
+ }
+
+ switch _g_.m.dying {
+ case 0:
+ _g_.m.dying = 1
+ if _g_ != nil {
+ _g_.writebuf = nil
+ }
+ xadd(&panicking, 1)
+ lock(&paniclk)
+ if debug.schedtrace > 0 || debug.scheddetail > 0 {
+ schedtrace(true)
+ }
+ 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
+ print("panic during panic\n")
+ dopanic(0)
+ exit(3)
+ fallthrough
+ case 2:
+ // This is a genuine bug in the runtime, we couldn't even
+ // print the stack trace successfully.
+ _g_.m.dying = 3
+ print("stack trace unavailable\n")
+ exit(4)
+ fallthrough
+ default:
+ // Can't even print! Just exit.
+ exit(5)
+ }
+}
+
+var didothers bool
+var deadlock mutex
+
+func dopanic_m(gp *g, pc, sp uintptr) {
+ if gp.sig != 0 {
+ print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
+ }
+
+ var docrash bool
+ _g_ := getg()
+ if t := gotraceback(&docrash); t > 0 {
+ if gp != gp.m.g0 {
+ print("\n")
+ goroutineheader(gp)
+ traceback(pc, sp, 0, gp)
+ } else if t >= 2 || _g_.m.throwing > 0 {
+ print("\nruntime stack:\n")
+ traceback(pc, sp, 0, gp)
+ }
+ if !didothers {
+ didothers = true
+ tracebackothers(gp)
+ }
+ }
+ unlock(&paniclk)
+
+ if xadd(&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.
+ lock(&deadlock)
+ lock(&deadlock)
+ }
+
+ if docrash {
+ crash()
+ }
+
+ exit(2)
+}
+
+//go:nosplit
+func canpanic(gp *g) bool {
+ // 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.
+ _g_ := getg()
+ _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_.preemptoff != "" || _m_.dying != 0 {
+ return false
+ }
+ status := readgstatus(gp)
+ if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
+ return false
+ }
+ if GOOS == "windows" && _m_.libcallsp != 0 {
+ return false
+ }
+ return true
+}
+++ /dev/null
-// 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.
-
-package runtime
-
-// Code related to defer, panic and recover.
-// TODO: Merge into panic.go.
-
-//uint32 runtime·panicking;
-var paniclk mutex
-
-const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
-
-// 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.
-func recovery(gp *g) {
- // Info about defer passed in G struct.
- sp := gp.sigcode0
- pc := gp.sigcode1
-
- // d's arguments need to be in the stack.
- if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
- print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
- 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.
- gcUnwindBarriers(gp, sp)
- gp.sched.sp = sp
- gp.sched.pc = pc
- gp.sched.lr = 0
- gp.sched.ret = 1
- gogo(&gp.sched)
-}
-
-func startpanic_m() {
- _g_ := getg()
- if mheap_.cachealloc.size == 0 { // very early
- print("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 = allocmcache()
- }
-
- switch _g_.m.dying {
- case 0:
- _g_.m.dying = 1
- if _g_ != nil {
- _g_.writebuf = nil
- }
- xadd(&panicking, 1)
- lock(&paniclk)
- if debug.schedtrace > 0 || debug.scheddetail > 0 {
- schedtrace(true)
- }
- 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
- print("panic during panic\n")
- dopanic(0)
- exit(3)
- fallthrough
- case 2:
- // This is a genuine bug in the runtime, we couldn't even
- // print the stack trace successfully.
- _g_.m.dying = 3
- print("stack trace unavailable\n")
- exit(4)
- fallthrough
- default:
- // Can't even print! Just exit.
- exit(5)
- }
-}
-
-var didothers bool
-var deadlock mutex
-
-func dopanic_m(gp *g, pc, sp uintptr) {
- if gp.sig != 0 {
- print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
- }
-
- var docrash bool
- _g_ := getg()
- if t := gotraceback(&docrash); t > 0 {
- if gp != gp.m.g0 {
- print("\n")
- goroutineheader(gp)
- traceback(pc, sp, 0, gp)
- } else if t >= 2 || _g_.m.throwing > 0 {
- print("\nruntime stack:\n")
- traceback(pc, sp, 0, gp)
- }
- if !didothers {
- didothers = true
- tracebackothers(gp)
- }
- }
- unlock(&paniclk)
-
- if xadd(&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.
- lock(&deadlock)
- lock(&deadlock)
- }
-
- if docrash {
- crash()
- }
-
- exit(2)
-}
-
-//go:nosplit
-func canpanic(gp *g) bool {
- // 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.
- _g_ := getg()
- _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_.preemptoff != "" || _m_.dying != 0 {
- return false
- }
- status := readgstatus(gp)
- if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
- return false
- }
- if GOOS == "windows" && _m_.libcallsp != 0 {
- return false
- }
- return true
-}