Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/mfixalloc.go

Documentation: runtime

     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   *sysMemStat
    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 *sysMemStat) {
    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