mirror of
https://github.com/golang/go
synced 2024-11-08 18:46:16 -07:00
28b5118415
m.gcing has become overloaded to mean "don't preempt this g" in general. Once the garbage collector is preemptible, the one thing it *won't* mean is that we're in the garbage collector. So, rename gcing to "preemptoff" and make it a string giving a reason that preemption is disabled. gcing was never set to anything but 0 or 1, so we don't have to worry about there being a stack of reasons. Change-Id: I4337c29e8e942e7aa4f106fc29597e1b5de4ef46 Reviewed-on: https://go-review.googlesource.com/3660 Reviewed-by: Russ Cox <rsc@golang.org>
115 lines
3.5 KiB
Go
115 lines
3.5 KiB
Go
// Copyright 2009 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"
|
|
|
|
// Note: the MemStats struct should be kept in sync with
|
|
// struct MStats in malloc.h
|
|
|
|
// A MemStats records statistics about the memory allocator.
|
|
type MemStats struct {
|
|
// General statistics.
|
|
Alloc uint64 // bytes allocated and still in use
|
|
TotalAlloc uint64 // bytes allocated (even if freed)
|
|
Sys uint64 // bytes obtained from system (sum of XxxSys below)
|
|
Lookups uint64 // number of pointer lookups
|
|
Mallocs uint64 // number of mallocs
|
|
Frees uint64 // number of frees
|
|
|
|
// Main allocation heap statistics.
|
|
HeapAlloc uint64 // bytes allocated and still in use
|
|
HeapSys uint64 // bytes obtained from system
|
|
HeapIdle uint64 // bytes in idle spans
|
|
HeapInuse uint64 // bytes in non-idle span
|
|
HeapReleased uint64 // bytes released to the OS
|
|
HeapObjects uint64 // total number of allocated objects
|
|
|
|
// Low-level fixed-size structure allocator statistics.
|
|
// Inuse is bytes used now.
|
|
// Sys is bytes obtained from system.
|
|
StackInuse uint64 // bytes used by stack allocator
|
|
StackSys uint64
|
|
MSpanInuse uint64 // mspan structures
|
|
MSpanSys uint64
|
|
MCacheInuse uint64 // mcache structures
|
|
MCacheSys uint64
|
|
BuckHashSys uint64 // profiling bucket hash table
|
|
GCSys uint64 // GC metadata
|
|
OtherSys uint64 // other system allocations
|
|
|
|
// Garbage collector statistics.
|
|
NextGC uint64 // next collection will happen when HeapAlloc ≥ this amount
|
|
LastGC uint64 // end time of last collection (nanoseconds since 1970)
|
|
PauseTotalNs uint64
|
|
PauseNs [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
|
|
PauseEnd [256]uint64 // circular buffer of recent GC pause end times
|
|
NumGC uint32
|
|
EnableGC bool
|
|
DebugGC bool
|
|
|
|
// Per-size allocation statistics.
|
|
// 61 is NumSizeClasses in the C code.
|
|
BySize [61]struct {
|
|
Size uint32
|
|
Mallocs uint64
|
|
Frees uint64
|
|
}
|
|
}
|
|
|
|
// Size of the trailing by_size array differs between Go and C,
|
|
// and all data after by_size is local to runtime, not exported.
|
|
// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
|
|
// sizeof_C_MStats is what C thinks about size of Go struct.
|
|
var sizeof_C_MStats = unsafe.Offsetof(memstats.by_size) + 61*unsafe.Sizeof(memstats.by_size[0])
|
|
|
|
func init() {
|
|
var memStats MemStats
|
|
if sizeof_C_MStats != unsafe.Sizeof(memStats) {
|
|
println(sizeof_C_MStats, unsafe.Sizeof(memStats))
|
|
throw("MStats vs MemStatsType size mismatch")
|
|
}
|
|
}
|
|
|
|
// ReadMemStats populates m with memory allocator statistics.
|
|
func ReadMemStats(m *MemStats) {
|
|
// Have to acquire worldsema to stop the world,
|
|
// because stoptheworld can only be used by
|
|
// one goroutine at a time, and there might be
|
|
// a pending garbage collection already calling it.
|
|
semacquire(&worldsema, false)
|
|
gp := getg()
|
|
gp.m.preemptoff = "read mem stats"
|
|
systemstack(stoptheworld)
|
|
|
|
systemstack(func() {
|
|
readmemstats_m(m)
|
|
})
|
|
|
|
gp.m.preemptoff = ""
|
|
gp.m.locks++
|
|
semrelease(&worldsema)
|
|
systemstack(starttheworld)
|
|
gp.m.locks--
|
|
}
|
|
|
|
//go:linkname runtime_debug_WriteHeapDump runtime/debug.WriteHeapDump
|
|
func runtime_debug_WriteHeapDump(fd uintptr) {
|
|
semacquire(&worldsema, false)
|
|
gp := getg()
|
|
gp.m.preemptoff = "write heap dump"
|
|
systemstack(stoptheworld)
|
|
|
|
systemstack(func() {
|
|
writeheapdump_m(fd)
|
|
})
|
|
|
|
gp.m.preemptoff = ""
|
|
gp.m.locks++
|
|
semrelease(&worldsema)
|
|
systemstack(starttheworld)
|
|
gp.m.locks--
|
|
}
|