Commit 4d226dfe authored by Russ Cox's avatar Russ Cox

runtime: move write barrier code into mbarrier.go

I also added new comments at the top of mbarrier.go,
but the rest of the code is just copy-and-paste.

Change-Id: Iaeb2b12f8b1eaa33dbff5c2de676ca902bfddf2e
Reviewed-on: https://go-review.googlesource.com/2990Reviewed-by: 's avatarAustin Clements <austin@google.com>
parent 7ef59e4e
...@@ -223,69 +223,6 @@ func mallocinit() { ...@@ -223,69 +223,6 @@ func mallocinit() {
_g_.m.mcache = allocmcache() _g_.m.mcache = allocmcache()
} }
func wbshadowinit() {
// Initialize write barrier shadow heap if we were asked for it
// and we have enough address space (not on 32-bit).
if debug.wbshadow == 0 {
return
}
if ptrSize != 8 {
print("runtime: GODEBUG=wbshadow=1 disabled on 32-bit system\n")
return
}
var reserved bool
p1 := sysReserveHigh(mheap_.arena_end-mheap_.arena_start, &reserved)
if p1 == nil {
throw("cannot map shadow heap")
}
mheap_.shadow_heap = uintptr(p1) - mheap_.arena_start
sysMap(p1, mheap_.arena_used-mheap_.arena_start, reserved, &memstats.other_sys)
memmove(p1, unsafe.Pointer(mheap_.arena_start), mheap_.arena_used-mheap_.arena_start)
mheap_.shadow_reserved = reserved
start := ^uintptr(0)
end := uintptr(0)
if start > uintptr(unsafe.Pointer(&noptrdata)) {
start = uintptr(unsafe.Pointer(&noptrdata))
}
if start > uintptr(unsafe.Pointer(&data)) {
start = uintptr(unsafe.Pointer(&data))
}
if start > uintptr(unsafe.Pointer(&noptrbss)) {
start = uintptr(unsafe.Pointer(&noptrbss))
}
if start > uintptr(unsafe.Pointer(&bss)) {
start = uintptr(unsafe.Pointer(&bss))
}
if end < uintptr(unsafe.Pointer(&enoptrdata)) {
end = uintptr(unsafe.Pointer(&enoptrdata))
}
if end < uintptr(unsafe.Pointer(&edata)) {
end = uintptr(unsafe.Pointer(&edata))
}
if end < uintptr(unsafe.Pointer(&enoptrbss)) {
end = uintptr(unsafe.Pointer(&enoptrbss))
}
if end < uintptr(unsafe.Pointer(&ebss)) {
end = uintptr(unsafe.Pointer(&ebss))
}
start &^= _PageSize - 1
end = round(end, _PageSize)
mheap_.data_start = start
mheap_.data_end = end
reserved = false
p1 = sysReserveHigh(end-start, &reserved)
if p1 == nil {
throw("cannot map shadow data")
}
mheap_.shadow_data = uintptr(p1) - start
sysMap(p1, end-start, reserved, &memstats.other_sys)
memmove(p1, unsafe.Pointer(start), end-start)
mheap_.shadow_enabled = true
}
// sysReserveHigh reserves space somewhere high in the address space. // sysReserveHigh reserves space somewhere high in the address space.
// sysReserve doesn't actually reserve the full amount requested on // sysReserve doesn't actually reserve the full amount requested on
// 64-bit systems, because of problems with ulimit. Instead it checks // 64-bit systems, because of problems with ulimit. Instead it checks
......
This diff is collapsed.
...@@ -1064,56 +1064,6 @@ func shade(b uintptr) { ...@@ -1064,56 +1064,6 @@ func shade(b uintptr) {
putpartial(wbuf) putpartial(wbuf)
} }
// This is the Dijkstra barrier coarsened to always shade the ptr (dst) object.
// The original Dijkstra barrier only shaded ptrs being placed in black slots.
//
// Shade indicates that it has seen a white pointer by adding the referent
// to wbuf as well as marking it.
//
// slot is the destination (dst) in go code
// ptr is the value that goes into the slot (src) in the go code
//
// Dijkstra pointed out that maintaining the no black to white
// pointers means that white to white pointers not need
// to be noted by the write barrier. Furthermore if either
// white object dies before it is reached by the
// GC then the object can be collected during this GC cycle
// instead of waiting for the next cycle. Unfortunately the cost of
// ensure that the object holding the slot doesn't concurrently
// change to black without the mutator noticing seems prohibitive.
//
// Consider the following example where the mutator writes into
// a slot and then loads the slot's mark bit while the GC thread
// writes to the slot's mark bit and then as part of scanning reads
// the slot.
//
// Initially both [slot] and [slotmark] are 0 (nil)
// Mutator thread GC thread
// st [slot], ptr st [slotmark], 1
//
// ld r1, [slotmark] ld r2, [slot]
//
// This is a classic example of independent reads of independent writes,
// aka IRIW. The question is if r1==r2==0 is allowed and for most HW the
// answer is yes without inserting a memory barriers between the st and the ld.
// These barriers are expensive so we have decided that we will
// always grey the ptr object regardless of the slot's color.
//go:nowritebarrier
func gcmarkwb_m(slot *uintptr, ptr uintptr) {
switch gcphase {
default:
throw("gcphasework in bad gcphase")
case _GCoff, _GCquiesce, _GCstw, _GCsweep, _GCscan:
// ok
case _GCmark, _GCmarktermination:
if ptr != 0 && inheap(ptr) {
shade(ptr)
}
}
}
// gchelpwork does a small bounded amount of gc work. The purpose is to // gchelpwork does a small bounded amount of gc work. The purpose is to
// shorten the time (as measured by allocations) spent doing a concurrent GC. // shorten the time (as measured by allocations) spent doing a concurrent GC.
// The number of mutator calls is roughly propotional to the number of allocations // The number of mutator calls is roughly propotional to the number of allocations
......
This diff is collapsed.
...@@ -22,7 +22,6 @@ const ( ...@@ -22,7 +22,6 @@ const (
const ( const (
uintptrMask = 1<<(8*ptrSize) - 1 uintptrMask = 1<<(8*ptrSize) - 1
poisonGC = uintptrMask & 0xf969696969696969
poisonStack = uintptrMask & 0x6868686868686868 poisonStack = uintptrMask & 0x6868686868686868
// Goroutine preemption request. // Goroutine preemption request.
...@@ -389,7 +388,7 @@ func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f ...@@ -389,7 +388,7 @@ func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f
case _BitsPointer: case _BitsPointer:
p := *(*unsafe.Pointer)(add(scanp, i*ptrSize)) p := *(*unsafe.Pointer)(add(scanp, i*ptrSize))
up := uintptr(p) up := uintptr(p)
if f != nil && 0 < up && up < _PageSize && debug.invalidptr != 0 || up == poisonGC || up == poisonStack { if f != nil && 0 < up && up < _PageSize && debug.invalidptr != 0 || up == poisonStack {
// Looks like a junk value in a pointer slot. // Looks like a junk value in a pointer slot.
// Live analysis wrong? // Live analysis wrong?
getg().m.traceback = 2 getg().m.traceback = 2
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment