blob: bb2f4e7e24534da4cd6dff57bad520758bb0a3e8 [file] [log] [blame]
Russ Cox1e2d2f02014-11-11 17:05:02 -05001// 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//
Keith Randallcd5b1442015-03-11 12:58:47 -07007// See malloc.go for overview.
Russ Cox1e2d2f02014-11-11 17:05:02 -05008
9package runtime
10
11import "unsafe"
12
Russ Cox484f8012015-02-19 13:38:46 -050013// 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 not zeroed.
18// The caller is responsible for locking around FixAlloc calls.
19// Callers can keep state in the object but the first word is
20// smashed by freeing and reallocating.
21type fixalloc struct {
22 size uintptr
23 first unsafe.Pointer // go func(unsafe.pointer, unsafe.pointer); f(arg, p) called first time p is returned
24 arg unsafe.Pointer
25 list *mlink
26 chunk *byte
27 nchunk uint32
28 inuse uintptr // in-use bytes now
29 stat *uint64
30}
31
32// A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).)
33// Since assignments to mlink.next will result in a write barrier being preformed
34// this can not be used by some of the internal GC structures. For example when
35// the sweeper is placing an unmarked object on the free list it does not want the
36// write barrier to be called since that could result in the object being reachable.
37type mlink struct {
38 next *mlink
39}
40
Russ Cox1e2d2f02014-11-11 17:05:02 -050041// Initialize f to allocate objects of the given size,
42// using the allocator to obtain chunks of memory.
43func fixAlloc_Init(f *fixalloc, size uintptr, first func(unsafe.Pointer, unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
44 f.size = size
45 f.first = *(*unsafe.Pointer)(unsafe.Pointer(&first))
46 f.arg = arg
47 f.list = nil
48 f.chunk = nil
49 f.nchunk = 0
50 f.inuse = 0
51 f.stat = stat
52}
53
54func fixAlloc_Alloc(f *fixalloc) unsafe.Pointer {
55 if f.size == 0 {
56 print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
Keith Randallb2a950b2014-12-27 20:58:00 -080057 throw("runtime: internal error")
Russ Cox1e2d2f02014-11-11 17:05:02 -050058 }
59
60 if f.list != nil {
61 v := unsafe.Pointer(f.list)
62 f.list = f.list.next
63 f.inuse += f.size
64 return v
65 }
66 if uintptr(f.nchunk) < f.size {
67 f.chunk = (*uint8)(persistentalloc(_FixAllocChunk, 0, f.stat))
68 f.nchunk = _FixAllocChunk
69 }
70
71 v := (unsafe.Pointer)(f.chunk)
72 if f.first != nil {
73 fn := *(*func(unsafe.Pointer, unsafe.Pointer))(unsafe.Pointer(&f.first))
74 fn(f.arg, v)
75 }
76 f.chunk = (*byte)(add(unsafe.Pointer(f.chunk), f.size))
77 f.nchunk -= uint32(f.size)
78 f.inuse += f.size
79 return v
80}
81
82func fixAlloc_Free(f *fixalloc, p unsafe.Pointer) {
83 f.inuse -= f.size
84 v := (*mlink)(p)
85 v.next = f.list
86 f.list = v
87}