Home | History | Annotate | Download | only in 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 manages 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