mirror of
https://github.com/golang/go
synced 2024-11-07 12:36:27 -07:00
8ebc58452a
This change modifies the type of several mstats fields to be a new type: sysMemStat. This type has the same structure as the fields used to have. The purpose of this change is to make it very clear which stats may be used in various functions for accounting (usually the platform-specific sys* functions, but there are others). Currently there's an implicit understanding that the *uint64 value passed to these functions is some kind of statistic whose value is atomically managed. This understanding isn't inherently problematic, but we're about to change how some stats (which currently use mSysStatInc and mSysStatDec) work, so we want to make it very clear what the various requirements are around "sysStat". This change also removes mSysStatInc and mSysStatDec in favor of a method on sysMemStat. Note that those two functions were originally written the way they were because atomic 64-bit adds required a valid G on ARM, but this hasn't been the case for a very long time (since golang.org/cl/14204, but even before then it wasn't clear if mutexes required a valid G anymore). Today we implement 64-bit adds on ARM with a spinlock table. Change-Id: I4e9b37cf14afc2ae20cf736e874eb0064af086d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/246971 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
100 lines
2.7 KiB
Go
100 lines
2.7 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.
|
|
|
|
// Fixed-size object allocator. Returned memory is not zeroed.
|
|
//
|
|
// See malloc.go for overview.
|
|
|
|
package runtime
|
|
|
|
import "unsafe"
|
|
|
|
// FixAlloc is a simple free-list allocator for fixed size objects.
|
|
// Malloc uses a FixAlloc wrapped around sysAlloc to manage its
|
|
// mcache and mspan objects.
|
|
//
|
|
// Memory returned by fixalloc.alloc is zeroed by default, but the
|
|
// caller may take responsibility for zeroing allocations by setting
|
|
// the zero flag to false. This is only safe if the memory never
|
|
// contains heap pointers.
|
|
//
|
|
// The caller is responsible for locking around FixAlloc calls.
|
|
// Callers can keep state in the object but the first word is
|
|
// smashed by freeing and reallocating.
|
|
//
|
|
// Consider marking fixalloc'd types go:notinheap.
|
|
type fixalloc struct {
|
|
size uintptr
|
|
first func(arg, p unsafe.Pointer) // called first time p is returned
|
|
arg unsafe.Pointer
|
|
list *mlink
|
|
chunk uintptr // use uintptr instead of unsafe.Pointer to avoid write barriers
|
|
nchunk uint32
|
|
inuse uintptr // in-use bytes now
|
|
stat *sysMemStat
|
|
zero bool // zero allocations
|
|
}
|
|
|
|
// A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).)
|
|
// Since assignments to mlink.next will result in a write barrier being performed
|
|
// this cannot be used by some of the internal GC structures. For example when
|
|
// the sweeper is placing an unmarked object on the free list it does not want the
|
|
// write barrier to be called since that could result in the object being reachable.
|
|
//
|
|
//go:notinheap
|
|
type mlink struct {
|
|
next *mlink
|
|
}
|
|
|
|
// Initialize f to allocate objects of the given size,
|
|
// using the allocator to obtain chunks of memory.
|
|
func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *sysMemStat) {
|
|
f.size = size
|
|
f.first = first
|
|
f.arg = arg
|
|
f.list = nil
|
|
f.chunk = 0
|
|
f.nchunk = 0
|
|
f.inuse = 0
|
|
f.stat = stat
|
|
f.zero = true
|
|
}
|
|
|
|
func (f *fixalloc) alloc() unsafe.Pointer {
|
|
if f.size == 0 {
|
|
print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
|
|
throw("runtime: internal error")
|
|
}
|
|
|
|
if f.list != nil {
|
|
v := unsafe.Pointer(f.list)
|
|
f.list = f.list.next
|
|
f.inuse += f.size
|
|
if f.zero {
|
|
memclrNoHeapPointers(v, f.size)
|
|
}
|
|
return v
|
|
}
|
|
if uintptr(f.nchunk) < f.size {
|
|
f.chunk = uintptr(persistentalloc(_FixAllocChunk, 0, f.stat))
|
|
f.nchunk = _FixAllocChunk
|
|
}
|
|
|
|
v := unsafe.Pointer(f.chunk)
|
|
if f.first != nil {
|
|
f.first(f.arg, v)
|
|
}
|
|
f.chunk = f.chunk + f.size
|
|
f.nchunk -= uint32(f.size)
|
|
f.inuse += f.size
|
|
return v
|
|
}
|
|
|
|
func (f *fixalloc) free(p unsafe.Pointer) {
|
|
f.inuse -= f.size
|
|
v := (*mlink)(p)
|
|
v.next = f.list
|
|
f.list = v
|
|
}
|