aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mbarrier.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-01-15 12:27:17 -0500
committerAustin Clements <austin@google.com>2018-02-13 16:34:46 +0000
commit20101894078199a3a9014ca99ec4e2a0a16a0869 (patch)
tree8e7ff5c0fcc37243fcd39ba23ea2976503712f63 /src/runtime/mbarrier.go
parent245310883dcae717bb662b22d5b1fd07fdd59b76 (diff)
downloadgo-20101894078199a3a9014ca99ec4e2a0a16a0869.tar.gz
go-20101894078199a3a9014ca99ec4e2a0a16a0869.zip
runtime: remove legacy eager write barrier
Now that the buffered write barrier is implemented for all architectures, we can remove the old eager write barrier implementation. This CL removes the implementation from the runtime, support in the compiler for calling it, and updates some compiler tests that relied on the old eager barrier support. It also makes sure that all of the useful comments from the old write barrier implementation still have a place to live. Fixes #22460. Updates #21640 since this fixes the layering concerns of the write barrier (but not the other things in that issue). Change-Id: I580f93c152e89607e0a72fe43370237ba97bae74 Reviewed-on: https://go-review.googlesource.com/92705 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Rick Hudson <rlh@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/mbarrier.go')
-rw-r--r--src/runtime/mbarrier.go121
1 files changed, 15 insertions, 106 deletions
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index e28bdb8b8d..c071728900 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -6,10 +6,10 @@
//
// For the concurrent garbage collector, the Go compiler implements
// updates to pointer-valued fields that may be in heap objects by
-// emitting calls to write barriers. This file contains the actual write barrier
-// implementation, gcmarkwb_m, and the various wrappers called by the
-// compiler to implement pointer assignment, slice assignment,
-// typed memmove, and so on.
+// emitting calls to write barriers. The main write barrier for
+// individual pointer writes is gcWriteBarrier and is implemented in
+// assembly. This file contains write barrier entry points for bulk
+// operations. See also mwbbuf.go.
package runtime
@@ -18,10 +18,7 @@ import (
"unsafe"
)
-// gcmarkwb_m is the mark-phase write barrier, the only barrier we have.
-// The rest of this file exists only to make calls to this function.
-//
-// This is a hybrid barrier that combines a Yuasa-style deletion
+// Go uses a hybrid barrier that combines a Yuasa-style deletion
// barrier—which shades the object whose reference is being
// overwritten—with Dijkstra insertion barrier—which shades the object
// whose reference is being written. The insertion part of the barrier
@@ -137,105 +134,17 @@ import (
// reachable by some goroutine that currently cannot reach it.
//
//
-//go:nowritebarrierrec
-//go:systemstack
-func gcmarkwb_m(slot *uintptr, ptr uintptr) {
- if writeBarrier.needed {
- // Note: This turns bad pointer writes into bad
- // pointer reads, which could be confusing. We avoid
- // reading from obviously bad pointers, which should
- // take care of the vast majority of these. We could
- // patch this up in the signal handler, or use XCHG to
- // combine the read and the write. Checking inheap is
- // insufficient since we need to track changes to
- // roots outside the heap.
- //
- // Note: profbuf.go omits a barrier during signal handler
- // profile logging; that's safe only because this deletion barrier exists.
- // If we remove the deletion barrier, we'll have to work out
- // a new way to handle the profile logging.
- if slot1 := uintptr(unsafe.Pointer(slot)); slot1 >= minPhysPageSize {
- if optr := *slot; optr != 0 {
- shade(optr)
- }
- }
- // TODO: Make this conditional on the caller's stack color.
- if ptr != 0 && inheap(ptr) {
- shade(ptr)
- }
- }
-}
-
-// writebarrierptr_prewrite1 invokes a write barrier for *dst = src
-// prior to the write happening.
-//
-// Write barrier calls must not happen during critical GC and scheduler
-// related operations. In particular there are times when the GC assumes
-// that the world is stopped but scheduler related code is still being
-// executed, dealing with syscalls, dealing with putting gs on runnable
-// queues and so forth. This code cannot execute write barriers because
-// the GC might drop them on the floor. Stopping the world involves removing
-// the p associated with an m. We use the fact that m.p == nil to indicate
-// that we are in one these critical section and throw if the write is of
-// a pointer to a heap object.
-//go:nosplit
-func writebarrierptr_prewrite1(dst *uintptr, src uintptr) {
- mp := acquirem()
- if mp.inwb || mp.dying > 0 {
- // We explicitly allow write barriers in startpanic_m,
- // since we're going down anyway. Ignore them here.
- releasem(mp)
- return
- }
- systemstack(func() {
- if mp.p == 0 && memstats.enablegc && !mp.inwb && inheap(src) {
- throw("writebarrierptr_prewrite1 called with mp.p == nil")
- }
- mp.inwb = true
- gcmarkwb_m(dst, src)
- })
- mp.inwb = false
- releasem(mp)
-}
-
-// NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer,
-// but if we do that, Go inserts a write barrier on *dst = src.
-//go:nosplit
-func writebarrierptr(dst *uintptr, src uintptr) {
- if writeBarrier.cgo {
- cgoCheckWriteBarrier(dst, src)
- }
- if !writeBarrier.needed {
- *dst = src
- return
- }
- if src != 0 && src < minPhysPageSize {
- systemstack(func() {
- print("runtime: writebarrierptr *", dst, " = ", hex(src), "\n")
- throw("bad pointer in write barrier")
- })
- }
- writebarrierptr_prewrite1(dst, src)
- *dst = src
-}
-
-// writebarrierptr_prewrite is like writebarrierptr, but the store
-// will be performed by the caller after this call. The caller must
-// not allow preemption between this call and the write.
+// Signal handler pointer writes:
//
-//go:nosplit
-func writebarrierptr_prewrite(dst *uintptr, src uintptr) {
- if writeBarrier.cgo {
- cgoCheckWriteBarrier(dst, src)
- }
- if !writeBarrier.needed {
- return
- }
- if src != 0 && src < minPhysPageSize {
- systemstack(func() { throw("bad pointer in write barrier") })
- }
- writebarrierptr_prewrite1(dst, src)
-}
+// In general, the signal handler cannot safely invoke the write
+// barrier because it may run without a P or even during the write
+// barrier.
+//
+// There is exactly one exception: profbuf.go omits a barrier during
+// signal handler profile logging. That's safe only because of the
+// deletion barrier. See profbuf.go for a detailed argument. If we
+// remove the deletion barrier, we'll have to work out a new way to
+// handle the profile logging.
// typedmemmove copies a value of type t to dst from src.
// Must be nosplit, see #16026.