mirror of https://github.com/golang/go.git
94 lines
2.1 KiB
Go
94 lines
2.1 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runtime
|
|
|
|
import _ "unsafe" // for go:linkname
|
|
|
|
//go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory
|
|
func runtime_debug_freeOSMemory() {
|
|
gogc(2) // force GC and do eager sweep
|
|
systemstack(scavenge_m)
|
|
}
|
|
|
|
var poolcleanup func()
|
|
|
|
//go:linkname sync_runtime_registerPoolCleanup sync.runtime_registerPoolCleanup
|
|
func sync_runtime_registerPoolCleanup(f func()) {
|
|
poolcleanup = f
|
|
}
|
|
|
|
func clearpools() {
|
|
// clear sync.Pools
|
|
if poolcleanup != nil {
|
|
poolcleanup()
|
|
}
|
|
|
|
for _, p := range &allp {
|
|
if p == nil {
|
|
break
|
|
}
|
|
// clear tinyalloc pool
|
|
if c := p.mcache; c != nil {
|
|
c.tiny = nil
|
|
c.tinyoffset = 0
|
|
|
|
// disconnect cached list before dropping it on the floor,
|
|
// so that a dangling ref to one entry does not pin all of them.
|
|
var sg, sgnext *sudog
|
|
for sg = c.sudogcache; sg != nil; sg = sgnext {
|
|
sgnext = sg.next
|
|
sg.next = nil
|
|
}
|
|
c.sudogcache = nil
|
|
}
|
|
|
|
// clear defer pools
|
|
for i := range p.deferpool {
|
|
// disconnect cached list before dropping it on the floor,
|
|
// so that a dangling ref to one entry does not pin all of them.
|
|
var d, dlink *_defer
|
|
for d = p.deferpool[i]; d != nil; d = dlink {
|
|
dlink = d.link
|
|
d.link = nil
|
|
}
|
|
p.deferpool[i] = nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// backgroundgc is running in a goroutine and does the concurrent GC work.
|
|
// bggc holds the state of the backgroundgc.
|
|
func backgroundgc() {
|
|
bggc.g = getg()
|
|
bggc.g.issystem = true
|
|
for {
|
|
gcwork(0)
|
|
lock(&bggc.lock)
|
|
bggc.working = 0
|
|
goparkunlock(&bggc.lock, "Concurrent GC wait", traceEvGoBlock)
|
|
}
|
|
}
|
|
|
|
func bgsweep() {
|
|
sweep.g = getg()
|
|
getg().issystem = true
|
|
for {
|
|
for gosweepone() != ^uintptr(0) {
|
|
sweep.nbgsweep++
|
|
Gosched()
|
|
}
|
|
lock(&gclock)
|
|
if !gosweepdone() {
|
|
// This can happen if a GC runs between
|
|
// gosweepone returning ^0 above
|
|
// and the lock being acquired.
|
|
unlock(&gclock)
|
|
continue
|
|
}
|
|
sweep.parked = true
|
|
goparkunlock(&gclock, "GC sweep wait", traceEvGoBlock)
|
|
}
|
|
}
|