aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-09-13 17:30:00 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-13 17:30:00 +0000
commitf0d89c7759e7be18895868e0c4e7f9e120f7890f (patch)
treeffb6a90f3e684836545e8c93e21e30588428ca11 /libgo
parent5f54d5fee46b8f1a0a78a8fbeb03e3ddfc8c9346 (diff)
downloadgcc-f0d89c7759e7be18895868e0c4e7f9e120f7890f.zip
gcc-f0d89c7759e7be18895868e0c4e7f9e120f7890f.tar.gz
gcc-f0d89c7759e7be18895868e0c4e7f9e120f7890f.tar.bz2
runtime: avoid write barriers with traceback info
Unlike the gc runtime, libgo stores traceback information in location structs, which contain strings. Therefore, copying location structs around appears to require write barriers, although in fact write barriers are never important because the strings are never allocated in Go memory. They come from libbacktrace. Some of the generated write barriers come at times when write barriers are not permitted. For example, exitsyscall, marked nowritebarrierrec, calls exitsyscallfast which calls traceGoSysExit which calls traceEvent which calls traceStackID which calls trace.stackTab.put which copies location values into memory allocated by tab.newStack. This write barrier can be invoked when there is no p, causing a crash. This change fixes the problem by ensuring that location values are copied around in the tracing code with no write barriers. This was found by fixing the compiler to fully implement //go:nowritebarrierrec; CL to follow. Reviewed-on: https://go-review.googlesource.com/134226 From-SVN: r264282
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/proc.go4
-rw-r--r--libgo/go/runtime/runtime2.go2
-rw-r--r--libgo/go/runtime/trace.go4
-rw-r--r--libgo/go/runtime/traceback_gccgo.go4
-rw-r--r--libgo/runtime/proc.c10
5 files changed, 13 insertions, 11 deletions
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index 74325e3..12d7071 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1140,7 +1140,7 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
func kickoff() {
gp := getg()
- if gp.traceback != nil {
+ if gp.traceback != 0 {
gtraceback(gp)
}
@@ -3097,7 +3097,7 @@ func newproc(fn uintptr, arg unsafe.Pointer) *g {
} else {
resetNewG(newg, &sp, &spsize)
}
- newg.traceback = nil
+ newg.traceback = 0
if readgstatus(newg) != _Gdead {
throw("newproc1: new g is not Gdead")
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index 0299d5a..2de1cc8 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -431,7 +431,7 @@ type g struct {
isSystemGoroutine bool // whether goroutine is a "system" goroutine
- traceback *tracebackg // stack traceback buffer
+ traceback uintptr // stack traceback buffer
context g_ucontext_t // saved context for setcontext
stackcontext [10]uintptr // split-stack context
diff --git a/libgo/go/runtime/trace.go b/libgo/go/runtime/trace.go
index 8427e76..e2bbb5d 100644
--- a/libgo/go/runtime/trace.go
+++ b/libgo/go/runtime/trace.go
@@ -135,6 +135,7 @@ var trace struct {
}
// traceBufHeader is per-P tracing buffer.
+//go:notinheap
type traceBufHeader struct {
link traceBufPtr // in trace.empty/full
lastTicks uint64 // when we wrote the last event
@@ -747,7 +748,8 @@ func (tab *traceStackTable) put(pcs []location) uint32 {
stk.n = len(pcs)
stkpc := stk.stack()
for i, pc := range pcs {
- stkpc[i] = pc
+ // Use memmove to avoid write barrier.
+ memmove(unsafe.Pointer(&stkpc[i]), unsafe.Pointer(&pc), unsafe.Sizeof(pc))
}
part := int(hash % uintptr(len(tab.tab)))
stk.link = tab.tab[part]
diff --git a/libgo/go/runtime/traceback_gccgo.go b/libgo/go/runtime/traceback_gccgo.go
index 8551ec1..9456b1f 100644
--- a/libgo/go/runtime/traceback_gccgo.go
+++ b/libgo/go/runtime/traceback_gccgo.go
@@ -186,7 +186,7 @@ func tracebackothers(me *g) {
if gp != nil && gp != me {
print("\n")
goroutineheader(gp)
- gp.traceback = (*tracebackg)(noescape(unsafe.Pointer(&tb)))
+ gp.traceback = (uintptr)(noescape(unsafe.Pointer(&tb)))
getTraceback(me, gp)
printtrace(tb.locbuf[:tb.c], nil)
printcreatedby(gp)
@@ -220,7 +220,7 @@ func tracebackothers(me *g) {
print("\tgoroutine in C code; stack unavailable\n")
printcreatedby(gp)
} else {
- gp.traceback = (*tracebackg)(noescape(unsafe.Pointer(&tb)))
+ gp.traceback = (uintptr)(noescape(unsafe.Pointer(&tb)))
getTraceback(me, gp)
printtrace(tb.locbuf[:tb.c], nil)
printcreatedby(gp)
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index d8d231ba..7bd95a0 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -338,7 +338,7 @@ runtime_mcall(FuncVal *fv)
gp = runtime_g();
mp = gp->m;
- if(gp->traceback != nil)
+ if(gp->traceback != 0)
gtraceback(gp);
}
if (gp == nil || !gp->fromgogo) {
@@ -443,7 +443,7 @@ void getTraceback(G* me, G* gp)
#endif
getcontext(ucontext_arg(&me->context[0]));
- if (gp->traceback != nil) {
+ if (gp->traceback != 0) {
runtime_gogo(gp);
}
}
@@ -457,8 +457,8 @@ gtraceback(G* gp)
Traceback* traceback;
M* holdm;
- traceback = gp->traceback;
- gp->traceback = nil;
+ traceback = (Traceback*)gp->traceback;
+ gp->traceback = 0;
holdm = gp->m;
if(holdm != nil && holdm != g->m)
runtime_throw("gtraceback: m is not nil");
@@ -510,7 +510,7 @@ runtime_mstart(void *arg)
// multiple times via the setcontext call in mcall.
getcontext(ucontext_arg(&gp->context[0]));
- if(gp->traceback != nil) {
+ if(gp->traceback != 0) {
// Got here from getTraceback.
// I'm not sure this ever actually happens--getTraceback
// may always go to the getcontext call in mcall.