...

Source file src/runtime/mfixalloc.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// Fixed-size object allocator. Returned memory is not zeroed.
     6	//
     7	// See malloc.go for overview.
     8	
     9	package runtime
    10	
    11	import "unsafe"
    12	
    13	// FixAlloc is a simple free-list allocator for fixed size objects.
    14	// Malloc uses a FixAlloc wrapped around sysAlloc to manage its
    15	// mcache and mspan objects.
    16	//
    17	// Memory returned by fixalloc.alloc is zeroed by default, but the
    18	// caller may take responsibility for zeroing allocations by setting
    19	// the zero flag to false. This is only safe if the memory never
    20	// contains heap pointers.
    21	//
    22	// The caller is responsible for locking around FixAlloc calls.
    23	// Callers can keep state in the object but the first word is
    24	// smashed by freeing and reallocating.
    25	//
    26	// Consider marking fixalloc'd types go:notinheap.
    27	type fixalloc struct {
    28		size   uintptr
    29		first  func(arg, p unsafe.Pointer) // called first time p is returned
    30		arg    unsafe.Pointer
    31		list   *mlink
    32		chunk  uintptr // use uintptr instead of unsafe.Pointer to avoid write barriers
    33		nchunk uint32
    34		inuse  uintptr // in-use bytes now
    35		stat   *uint64
    36		zero   bool // zero allocations
    37	}
    38	
    39	// A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
    40	// Since assignments to mlink.next will result in a write barrier being performed
    41	// this cannot be used by some of the internal GC structures. For example when
    42	// the sweeper is placing an unmarked object on the free list it does not want the
    43	// write barrier to be called since that could result in the object being reachable.
    44	//
    45	//go:notinheap
    46	type mlink struct {
    47		next *mlink
    48	}
    49	
    50	// Initialize f to allocate objects of the given size,
    51	// using the allocator to obtain chunks of memory.
    52	func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
    53		f.size = size
    54		f.first = first
    55		f.arg = arg
    56		f.list = nil
    57		f.chunk = 0
    58		f.nchunk = 0
    59		f.inuse = 0
    60		f.stat = stat
    61		f.zero = true
    62	}
    63	
    64	func (f *fixalloc) alloc() unsafe.Pointer {
    65		if f.size == 0 {
    66			print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
    67			throw("runtime: internal error")
    68		}
    69	
    70		if f.list != nil {
    71			v := unsafe.Pointer(f.list)
    72			f.list = f.list.next
    73			f.inuse += f.size
    74			if f.zero {
    75				memclrNoHeapPointers(v, f.size)
    76			}
    77			return v
    78		}
    79		if uintptr(f.nchunk) < f.size {
    80			f.chunk = uintptr(persistentalloc(_FixAllocChunk, 0, f.stat))
    81			f.nchunk = _FixAllocChunk
    82		}
    83	
    84		v := unsafe.Pointer(f.chunk)
    85		if f.first != nil {
    86			f.first(f.arg, v)
    87		}
    88		f.chunk = f.chunk + f.size
    89		f.nchunk -= uint32(f.size)
    90		f.inuse += f.size
    91		return v
    92	}
    93	
    94	func (f *fixalloc) free(p unsafe.Pointer) {
    95		f.inuse -= f.size
    96		v := (*mlink)(p)
    97		v.next = f.list
    98		f.list = v
    99	}
   100	

View as plain text