]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: refactor coalescing into its own method
authorMichael Anthony Knyszek <mknyszek@google.com>
Mon, 14 Jan 2019 21:27:29 +0000 (21:27 +0000)
committerMichael Knyszek <mknyszek@google.com>
Thu, 17 Jan 2019 16:59:49 +0000 (16:59 +0000)
The coalescing process is complex and in a follow-up change we'll need
to do it in more than one place, so this change factors out the
coalescing code in freeSpanLocked into a method on mheap.

Change-Id: Ia266b6cb1157c1b8d3d8a4287b42fbcc032bbf3a
Reviewed-on: https://go-review.googlesource.com/c/157838
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
src/runtime/mheap.go

index f5b5ba99b8418a0f01a83495f75ca3b1ec601001..d4096624514609f3e6f816baa69930017a7922bc 100644 (file)
@@ -419,6 +419,65 @@ func (s *mspan) physPageBounds() (uintptr, uintptr) {
        return start, end
 }
 
+func (h *mheap) coalesce(s *mspan) {
+       // We scavenge s at the end after coalescing if s or anything
+       // it merged with is marked scavenged.
+       needsScavenge := false
+       prescavenged := s.released() // number of bytes already scavenged.
+
+       // Coalesce with earlier, later spans.
+       if before := spanOf(s.base() - 1); before != nil && before.state == mSpanFree {
+               // Now adjust s.
+               s.startAddr = before.startAddr
+               s.npages += before.npages
+               s.needzero |= before.needzero
+               h.setSpan(before.base(), s)
+               // If before or s are scavenged, then we need to scavenge the final coalesced span.
+               needsScavenge = needsScavenge || before.scavenged || s.scavenged
+               prescavenged += before.released()
+               // The size is potentially changing so the treap needs to delete adjacent nodes and
+               // insert back as a combined node.
+               if before.scavenged {
+                       h.scav.removeSpan(before)
+               } else {
+                       h.free.removeSpan(before)
+               }
+               before.state = mSpanDead
+               h.spanalloc.free(unsafe.Pointer(before))
+       }
+
+       // Now check to see if next (greater addresses) span is free and can be coalesced.
+       if after := spanOf(s.base() + s.npages*pageSize); after != nil && after.state == mSpanFree {
+               s.npages += after.npages
+               s.needzero |= after.needzero
+               h.setSpan(s.base()+s.npages*pageSize-1, s)
+               needsScavenge = needsScavenge || after.scavenged || s.scavenged
+               prescavenged += after.released()
+               if after.scavenged {
+                       h.scav.removeSpan(after)
+               } else {
+                       h.free.removeSpan(after)
+               }
+               after.state = mSpanDead
+               h.spanalloc.free(unsafe.Pointer(after))
+       }
+
+       if needsScavenge {
+               // When coalescing spans, some physical pages which
+               // were not returned to the OS previously because
+               // they were only partially covered by the span suddenly
+               // become available for scavenging. We want to make sure
+               // those holes are filled in, and the span is properly
+               // scavenged. Rather than trying to detect those holes
+               // directly, we collect how many bytes were already
+               // scavenged above and subtract that from heap_released
+               // before re-scavenging the entire newly-coalesced span,
+               // which will implicitly bump up heap_released.
+               memstats.heap_released -= uint64(prescavenged)
+               s.scavenge()
+       }
+}
+
 func (s *mspan) scavenge() uintptr {
        // start and end must be rounded in, otherwise madvise
        // will round them *out* and release more memory
@@ -1215,62 +1274,8 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
                s.unusedsince = nanotime()
        }
 
-       // We scavenge s at the end after coalescing if s or anything
-       // it merged with is marked scavenged.
-       needsScavenge := false
-       prescavenged := s.released() // number of bytes already scavenged.
-
-       // Coalesce with earlier, later spans.
-       if before := spanOf(s.base() - 1); before != nil && before.state == mSpanFree {
-               // Now adjust s.
-               s.startAddr = before.startAddr
-               s.npages += before.npages
-               s.needzero |= before.needzero
-               h.setSpan(before.base(), s)
-               // If before or s are scavenged, then we need to scavenge the final coalesced span.
-               needsScavenge = needsScavenge || before.scavenged || s.scavenged
-               prescavenged += before.released()
-               // The size is potentially changing so the treap needs to delete adjacent nodes and
-               // insert back as a combined node.
-               if before.scavenged {
-                       h.scav.removeSpan(before)
-               } else {
-                       h.free.removeSpan(before)
-               }
-               before.state = mSpanDead
-               h.spanalloc.free(unsafe.Pointer(before))
-       }
-
-       // Now check to see if next (greater addresses) span is free and can be coalesced.
-       if after := spanOf(s.base() + s.npages*pageSize); after != nil && after.state == mSpanFree {
-               s.npages += after.npages
-               s.needzero |= after.needzero
-               h.setSpan(s.base()+s.npages*pageSize-1, s)
-               needsScavenge = needsScavenge || after.scavenged || s.scavenged
-               prescavenged += after.released()
-               if after.scavenged {
-                       h.scav.removeSpan(after)
-               } else {
-                       h.free.removeSpan(after)
-               }
-               after.state = mSpanDead
-               h.spanalloc.free(unsafe.Pointer(after))
-       }
-
-       if needsScavenge {
-               // When coalescing spans, some physical pages which
-               // were not returned to the OS previously because
-               // they were only partially covered by the span suddenly
-               // become available for scavenging. We want to make sure
-               // those holes are filled in, and the span is properly
-               // scavenged. Rather than trying to detect those holes
-               // directly, we collect how many bytes were already
-               // scavenged above and subtract that from heap_released
-               // before re-scavenging the entire newly-coalesced span,
-               // which will implicitly bump up heap_released.
-               memstats.heap_released -= uint64(prescavenged)
-               s.scavenge()
-       }
+       // Coalesce span with neighbors.
+       h.coalesce(s)
 
        // Insert s into the appropriate treap.
        if s.scavenged {