aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/cgocall.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2016-04-27 14:18:29 -0700
committerIan Lance Taylor <iant@golang.org>2016-04-29 22:07:36 +0000
commit5f9a870bf1bf461ca3609502608b12cc4aab189a (patch)
tree8acea9b2b421e8a188b27872a00c935f3f8776c3 /src/runtime/cgocall.go
parentc717675c35cb436bdab62091a6288843aa1c863c (diff)
downloadgo-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.go35
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))