2018-03-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / mfixalloc.go
blob7496671fbec151808497a43b8b87af8bfb99d9f9
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.
5 // Fixed-size object allocator. Returned memory is not zeroed.
6 //
7 // See malloc.go for overview.
9 package runtime
11 import "unsafe"
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.
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.
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.
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
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.
45 //go:notinheap
46 type mlink struct {
47 next *mlink
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
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")
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)
77 return v
79 if uintptr(f.nchunk) < f.size {
80 f.chunk = uintptr(persistentalloc(_FixAllocChunk, 0, f.stat))
81 f.nchunk = _FixAllocChunk
84 v := unsafe.Pointer(f.chunk)
85 if f.first != nil {
86 f.first(f.arg, v)
88 f.chunk = f.chunk + f.size
89 f.nchunk -= uint32(f.size)
90 f.inuse += f.size
91 return v
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