aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-09-13 22:25:58 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-13 22:25:58 +0000
commitcec07c4759e8af44ca77a2beb9312e4e30d1cc7a (patch)
tree38fe52c7aeba372693d83041bf5037d8fbb2c311 /libgo
parent38fab7369d19fd545eb8510ec198e73949a2c75d (diff)
downloadgcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.zip
gcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.tar.gz
gcc-cec07c4759e8af44ca77a2beb9312e4e30d1cc7a.tar.bz2
compiler, runtime: call gcWriteBarrier instead of writebarrierptr
In 1.11 writebarrierptr is going away, so change the compiler to call gcWriteBarrier instead. We weren't using gcWriteBarrier before; adjust the implementation to use the putFast method. This revealed a problem in the kickoff function. When using cgo, kickoff can be called on the g0 of an m allocated by newExtraM. In that case the m will generally have a p, but systemstack may be called by wbBufFlush as part of flushing the write barrier buffer. At that point the buffer is full, so we can not do a write barrier. So adjust the existing code in kickoff so that in the case where we are g0, don't do any write barrier at all. Reviewed-on: https://go-review.googlesource.com/131395 From-SVN: r264295
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/mgc_gccgo.go12
-rw-r--r--libgo/go/runtime/proc.go35
2 files changed, 26 insertions, 21 deletions
diff --git a/libgo/go/runtime/mgc_gccgo.go b/libgo/go/runtime/mgc_gccgo.go
index cf7780c..b396d35 100644
--- a/libgo/go/runtime/mgc_gccgo.go
+++ b/libgo/go/runtime/mgc_gccgo.go
@@ -11,6 +11,11 @@ import (
"unsafe"
)
+// For gccgo, use go:linkname to rename compiler-called functions to
+// themselves, so that the compiler will export them.
+//
+//go:linkname gcWriteBarrier runtime.gcWriteBarrier
+
// gcRoot is a single GC root: a variable plus a ptrmask.
//go:notinheap
type gcRoot struct {
@@ -188,12 +193,7 @@ func checkPreempt() {
//go:nowritebarrier
func gcWriteBarrier(dst *uintptr, src uintptr) {
buf := &getg().m.p.ptr().wbBuf
- next := buf.next
- np := next + 2*sys.PtrSize
- buf.next = np
- *(*uintptr)(unsafe.Pointer(next)) = src
- *(*uintptr)(unsafe.Pointer(next + sys.PtrSize)) = *dst
- if np >= buf.end {
+ if !buf.putFast(src, *dst) {
wbBufFlush(dst, src)
}
*dst = src
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index 12d7071..4fc45dd 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1146,24 +1146,29 @@ func kickoff() {
fv := gp.entry
param := gp.param
- gp.entry = nil
// When running on the g0 stack we can wind up here without a p,
- // for example from mcall(exitsyscall0) in exitsyscall.
- // Setting gp.param = nil will call a write barrier, and if
- // there is no p that write barrier will crash. When called from
- // mcall the gp.param value will be a *g, which we don't need to
- // shade since we know it will be kept alive elsewhere. In that
- // case clear the field using uintptr so that the write barrier
- // does nothing.
- if gp.m.p == 0 {
- if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) {
- *(*uintptr)(unsafe.Pointer(&gp.param)) = 0
- } else {
- throw("no p in kickoff")
- }
+ // for example from mcall(exitsyscall0) in exitsyscall, in
+ // which case we can not run a write barrier.
+ // It is also possible for us to get here from the systemstack
+ // call in wbBufFlush, at which point the write barrier buffer
+ // is full and we can not run a write barrier.
+ // Setting gp.entry = nil or gp.param = nil will try to run a
+ // write barrier, so if we are on the g0 stack due to mcall
+ // (systemstack calls mcall) then clear the field using uintptr.
+ // This is OK when gp.param is gp.m.curg, as curg will be kept
+ // alive elsewhere, and gp.entry always points into g, or
+ // to a statically allocated value, or (in the case of mcall)
+ // to the stack.
+ if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) {
+ *(*uintptr)(unsafe.Pointer(&gp.entry)) = 0
+ *(*uintptr)(unsafe.Pointer(&gp.param)) = 0
+ } else if gp.m.p == 0 {
+ throw("no p in kickoff")
+ } else {
+ gp.entry = nil
+ gp.param = nil
}
- gp.param = nil
fv(param)
goexit1()