1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:20:04 -07:00

runtime: abstract remaining mheap.spans access

This abstracts the remaining direct accesses to mheap.spans into new
mheap.setSpan and mheap.setSpans methods.

For #10460.

Change-Id: Id1db8bc5e34a77a9221032aa2e62d05322707364
Reviewed-on: https://go-review.googlesource.com/85884
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2017-12-13 16:03:23 -05:00
parent c0392d2e7f
commit 0de5324d61

View File

@ -806,6 +806,20 @@ func (h *mheap) allocManual(npage uintptr, stat *uint64) *mspan {
return s return s
} }
// setSpan modifies the span map so spanOf(base) is s.
func (h *mheap) setSpan(base uintptr, s *mspan) {
h.spans[(base-h.arena_start)>>_PageShift] = s
}
// setSpans modifies the span map so [spanOf(base), spanOf(base+npage*pageSize))
// is s.
func (h *mheap) setSpans(base, npage uintptr, s *mspan) {
p := (base - h.arena_start) >> _PageShift
for n := uintptr(0); n < npage; n++ {
h.spans[p+n] = s
}
}
// Allocates a span of the given size. h must be locked. // Allocates a span of the given size. h must be locked.
// The returned span has been removed from the // The returned span has been removed from the
// free list, but its state is still MSpanFree. // free list, but its state is still MSpanFree.
@ -853,12 +867,9 @@ HaveSpan:
t := (*mspan)(h.spanalloc.alloc()) t := (*mspan)(h.spanalloc.alloc())
t.init(s.base()+npage<<_PageShift, s.npages-npage) t.init(s.base()+npage<<_PageShift, s.npages-npage)
s.npages = npage s.npages = npage
p := (t.base() - h.arena_start) >> _PageShift h.setSpan(t.base()-1, s)
if p > 0 { h.setSpan(t.base(), t)
h.spans[p-1] = s h.setSpan(t.base()+t.npages*pageSize-1, t)
}
h.spans[p] = t
h.spans[p+t.npages-1] = t
t.needzero = s.needzero t.needzero = s.needzero
s.state = _MSpanManual // prevent coalescing with s s.state = _MSpanManual // prevent coalescing with s
t.state = _MSpanManual t.state = _MSpanManual
@ -867,10 +878,7 @@ HaveSpan:
} }
s.unusedsince = 0 s.unusedsince = 0
p := (s.base() - h.arena_start) >> _PageShift h.setSpans(s.base(), npage, s)
for n := uintptr(0); n < npage; n++ {
h.spans[p+n] = s
}
*stat += uint64(npage << _PageShift) *stat += uint64(npage << _PageShift)
memstats.heap_idle -= uint64(npage << _PageShift) memstats.heap_idle -= uint64(npage << _PageShift)
@ -928,10 +936,7 @@ func (h *mheap) grow(npage uintptr) bool {
// right coalescing happens. // right coalescing happens.
s := (*mspan)(h.spanalloc.alloc()) s := (*mspan)(h.spanalloc.alloc())
s.init(uintptr(v), ask>>_PageShift) s.init(uintptr(v), ask>>_PageShift)
p := (s.base() - h.arena_start) >> _PageShift h.setSpans(s.base(), s.npages, s)
for i := p; i < p+s.npages; i++ {
h.spans[i] = s
}
atomic.Store(&s.sweepgen, h.sweepgen) atomic.Store(&s.sweepgen, h.sweepgen)
s.state = _MSpanInUse s.state = _MSpanInUse
h.pagesInUse += uint64(s.npages) h.pagesInUse += uint64(s.npages)
@ -1023,17 +1028,13 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
s.npreleased = 0 s.npreleased = 0
// Coalesce with earlier, later spans. // Coalesce with earlier, later spans.
p := (s.base() - h.arena_start) >> _PageShift if before := spanOf(s.base() - 1); before != nil && before.state == _MSpanFree {
if p > 0 {
before := h.spans[p-1]
if before != nil && before.state == _MSpanFree {
// Now adjust s. // Now adjust s.
s.startAddr = before.startAddr s.startAddr = before.startAddr
s.npages += before.npages s.npages += before.npages
s.npreleased = before.npreleased // absorb released pages s.npreleased = before.npreleased // absorb released pages
s.needzero |= before.needzero s.needzero |= before.needzero
p -= before.npages h.setSpan(before.base(), s)
h.spans[p] = s
// The size is potentially changing so the treap needs to delete adjacent nodes and // The size is potentially changing so the treap needs to delete adjacent nodes and
// insert back as a combined node. // insert back as a combined node.
if h.isLargeSpan(before.npages) { if h.isLargeSpan(before.npages) {
@ -1045,16 +1046,13 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
before.state = _MSpanDead before.state = _MSpanDead
h.spanalloc.free(unsafe.Pointer(before)) h.spanalloc.free(unsafe.Pointer(before))
} }
}
// Now check to see if next (greater addresses) span is free and can be coalesced. // Now check to see if next (greater addresses) span is free and can be coalesced.
if (p + s.npages) < uintptr(len(h.spans)) { if after := spanOf(s.base() + s.npages*pageSize); after != nil && after.state == _MSpanFree {
after := h.spans[p+s.npages]
if after != nil && after.state == _MSpanFree {
s.npages += after.npages s.npages += after.npages
s.npreleased += after.npreleased s.npreleased += after.npreleased
s.needzero |= after.needzero s.needzero |= after.needzero
h.spans[p+s.npages-1] = s h.setSpan(s.base()+s.npages*pageSize-1, s)
if h.isLargeSpan(after.npages) { if h.isLargeSpan(after.npages) {
h.freelarge.removeSpan(after) h.freelarge.removeSpan(after)
} else { } else {
@ -1063,7 +1061,6 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
after.state = _MSpanDead after.state = _MSpanDead
h.spanalloc.free(unsafe.Pointer(after)) h.spanalloc.free(unsafe.Pointer(after))
} }
}
// Insert s into appropriate list or treap. // Insert s into appropriate list or treap.
if h.isLargeSpan(s.npages) { if h.isLargeSpan(s.npages) {