Source file
src/runtime/mfixalloc.go
1
2
3
4
5
6
7
8
9 package runtime
10
11 import (
12 "runtime/internal/sys"
13 "unsafe"
14 )
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 type fixalloc struct {
32 size uintptr
33 first func(arg, p unsafe.Pointer)
34 arg unsafe.Pointer
35 list *mlink
36 chunk uintptr
37 nchunk uint32
38 nalloc uint32
39 inuse uintptr
40 stat *sysMemStat
41 zero bool
42 }
43
44
45
46
47
48
49 type mlink struct {
50 _ sys.NotInHeap
51 next *mlink
52 }
53
54
55
56 func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *sysMemStat) {
57 if size > _FixAllocChunk {
58 throw("runtime: fixalloc size too large")
59 }
60 if min := unsafe.Sizeof(mlink{}); size < min {
61 size = min
62 }
63
64 f.size = size
65 f.first = first
66 f.arg = arg
67 f.list = nil
68 f.chunk = 0
69 f.nchunk = 0
70 f.nalloc = uint32(_FixAllocChunk / size * size)
71 f.inuse = 0
72 f.stat = stat
73 f.zero = true
74 }
75
76 func (f *fixalloc) alloc() unsafe.Pointer {
77 if f.size == 0 {
78 print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
79 throw("runtime: internal error")
80 }
81
82 if f.list != nil {
83 v := unsafe.Pointer(f.list)
84 f.list = f.list.next
85 f.inuse += f.size
86 if f.zero {
87 memclrNoHeapPointers(v, f.size)
88 }
89 return v
90 }
91 if uintptr(f.nchunk) < f.size {
92 f.chunk = uintptr(persistentalloc(uintptr(f.nalloc), 0, f.stat))
93 f.nchunk = f.nalloc
94 }
95
96 v := unsafe.Pointer(f.chunk)
97 if f.first != nil {
98 f.first(f.arg, v)
99 }
100 f.chunk = f.chunk + f.size
101 f.nchunk -= uint32(f.size)
102 f.inuse += f.size
103 return v
104 }
105
106 func (f *fixalloc) free(p unsafe.Pointer) {
107 f.inuse -= f.size
108 v := (*mlink)(p)
109 v.next = f.list
110 f.list = v
111 }
112
View as plain text