diff options
author | Ian Lance Taylor <iant@golang.org> | 2016-04-27 14:18:29 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2016-04-29 22:07:36 +0000 |
commit | 5f9a870bf1bf461ca3609502608b12cc4aab189a (patch) | |
tree | 8acea9b2b421e8a188b27872a00c935f3f8776c3 /src/runtime/cgocall.go | |
parent | c717675c35cb436bdab62091a6288843aa1c863c (diff) | |
download | go-5f9a870bf1bf461ca3609502608b12cc4aab189a.tar.gz go-5f9a870bf1bf461ca3609502608b12cc4aab189a.zip |
cmd/cgo, runtime, runtime/cgo: use cgo context function
Add support for the context function set by runtime.SetCgoTraceback.
The context function was added in CL 17761, without support.
This CL is the support.
This CL has not been tested for real C code, as a working context
function for C code requires unwind support that does not seem to exist.
I wanted to get the CL out before the freeze.
I apologize for the length of this CL. It's mostly plumbing, but
unfortunately the plumbing is processor-specific.
Change-Id: I8ce11a0de9b3dafcc29efd2649d776e93bff0e90
Reviewed-on: https://go-review.googlesource.com/22508
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/cgocall.go')
-rw-r--r-- | src/runtime/cgocall.go | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index be234345d1..fa996d2405 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -166,7 +166,7 @@ func cfree(p unsafe.Pointer) { // Call from C back to Go. //go:nosplit -func cgocallbackg() { +func cgocallbackg(ctxt uintptr) { gp := getg() if gp != gp.m.curg { println("runtime: bad g in cgocallback") @@ -184,20 +184,43 @@ func cgocallbackg() { savedsp := unsafe.Pointer(gp.syscallsp) savedpc := gp.syscallpc exitsyscall(0) // coming out of cgo call - cgocallbackg1() + + cgocallbackg1(ctxt) + // going back to cgo call reentersyscall(savedpc, uintptr(savedsp)) gp.m.syscall = syscall } -func cgocallbackg1() { +func cgocallbackg1(ctxt uintptr) { gp := getg() if gp.m.needextram { gp.m.needextram = false systemstack(newextram) } + if ctxt != 0 { + s := append(gp.cgoCtxt, ctxt) + + // Now we need to set gp.cgoCtxt = s, but we could get + // a SIGPROF signal while manipulating the slice, and + // the SIGPROF handler could pick up gp.cgoCtxt while + // tracing up the stack. We need to ensure that the + // handler always sees a valid slice, so set the + // values in an order such that it always does. + p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) + atomicstorep(unsafe.Pointer(&p.array), unsafe.Pointer(&s[0])) + p.cap = cap(s) + p.len = len(s) + + defer func(gp *g) { + // Decrease the length of the slice by one, safely. + p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) + p.len-- + }(gp) + } + if gp.m.ncgo == 0 { // The C call to Go came from a thread not currently running // any Go. In the case of -buildmode=c-archive or c-shared, @@ -236,13 +259,13 @@ func cgocallbackg1() { // SP and the stack frame and between the stack frame and the arguments. cb = (*args)(unsafe.Pointer(sp + 5*sys.PtrSize)) case "amd64": - // On amd64, stack frame is one word, plus caller PC. + // On amd64, stack frame is two words, plus caller PC. if framepointer_enabled { // In this case, there's also saved BP. - cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize)) + cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize)) break } - cb = (*args)(unsafe.Pointer(sp + 2*sys.PtrSize)) + cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize)) case "386": // On 386, stack frame is three words, plus caller PC. cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize)) |