Source file
src/runtime/mem_sbrk.go
1
2
3
4
5
6
7 package runtime
8
9 import "unsafe"
10
11 const isSbrkPlatform = true
12
13 const memDebug = false
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 var bloc uintptr
36 var blocMax uintptr
37 var memlock mutex
38
39 type memHdr struct {
40 next memHdrPtr
41 size uintptr
42 }
43
44 var memFreelist memHdrPtr
45
46 type memHdrPtr uintptr
47
48 func (p memHdrPtr) ptr() *memHdr { return (*memHdr)(unsafe.Pointer(p)) }
49 func (p *memHdrPtr) set(x *memHdr) { *p = memHdrPtr(unsafe.Pointer(x)) }
50
51 func memAlloc(n uintptr) unsafe.Pointer {
52 if p := memAllocNoGrow(n); p != nil {
53 return p
54 }
55 return sbrk(n)
56 }
57
58 func memAllocNoGrow(n uintptr) unsafe.Pointer {
59 n = memRound(n)
60 var prevp *memHdr
61 for p := memFreelist.ptr(); p != nil; p = p.next.ptr() {
62 if p.size >= n {
63 if p.size == n {
64 if prevp != nil {
65 prevp.next = p.next
66 } else {
67 memFreelist = p.next
68 }
69 } else {
70 p.size -= n
71 p = (*memHdr)(add(unsafe.Pointer(p), p.size))
72 }
73 *p = memHdr{}
74 return unsafe.Pointer(p)
75 }
76 prevp = p
77 }
78 return nil
79 }
80
81 func memFree(ap unsafe.Pointer, n uintptr) {
82 n = memRound(n)
83 memclrNoHeapPointers(ap, n)
84 bp := (*memHdr)(ap)
85 bp.size = n
86 bpn := uintptr(ap)
87 if memFreelist == 0 {
88 bp.next = 0
89 memFreelist.set(bp)
90 return
91 }
92 p := memFreelist.ptr()
93 if bpn < uintptr(unsafe.Pointer(p)) {
94 memFreelist.set(bp)
95 if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
96 bp.size += p.size
97 bp.next = p.next
98 *p = memHdr{}
99 } else {
100 bp.next.set(p)
101 }
102 return
103 }
104 for ; p.next != 0; p = p.next.ptr() {
105 if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) {
106 break
107 }
108 }
109 if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
110 bp.size += p.next.ptr().size
111 bp.next = p.next.ptr().next
112 *p.next.ptr() = memHdr{}
113 } else {
114 bp.next = p.next
115 }
116 if uintptr(unsafe.Pointer(p))+p.size == bpn {
117 p.size += bp.size
118 p.next = bp.next
119 *bp = memHdr{}
120 } else {
121 p.next.set(bp)
122 }
123 }
124
125 func memCheck() {
126 if !memDebug {
127 return
128 }
129 for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() {
130 if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) {
131 print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n")
132 throw("mem: infinite loop")
133 }
134 if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) {
135 print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n")
136 throw("mem: unordered list")
137 }
138 if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) {
139 print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n")
140 throw("mem: overlapping blocks")
141 }
142 for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) {
143 if *(*byte)(b) != 0 {
144 print("runtime: value at addr ", b, " with offset ", uintptr(b)-uintptr(unsafe.Pointer(p)), " in block ", p, " of size ", p.size, " is not zero\n")
145 throw("mem: uninitialised memory")
146 }
147 }
148 }
149 }
150
151 func memRound(p uintptr) uintptr {
152 return alignUp(p, physPageSize)
153 }
154
155 func initBloc() {
156 bloc = memRound(firstmoduledata.end)
157 blocMax = bloc
158 }
159
160 func sysAllocOS(n uintptr) unsafe.Pointer {
161 lock(&memlock)
162 p := memAlloc(n)
163 memCheck()
164 unlock(&memlock)
165 return p
166 }
167
168 func sysFreeOS(v unsafe.Pointer, n uintptr) {
169 lock(&memlock)
170 if uintptr(v)+n == bloc {
171
172
173
174 memclrNoHeapPointers(v, n)
175 bloc -= n
176 } else {
177 memFree(v, n)
178 memCheck()
179 }
180 unlock(&memlock)
181 }
182
183 func sysUnusedOS(v unsafe.Pointer, n uintptr) {
184 }
185
186 func sysUsedOS(v unsafe.Pointer, n uintptr) {
187 }
188
189 func sysHugePageOS(v unsafe.Pointer, n uintptr) {
190 }
191
192 func sysNoHugePageOS(v unsafe.Pointer, n uintptr) {
193 }
194
195 func sysHugePageCollapseOS(v unsafe.Pointer, n uintptr) {
196 }
197
198 func sysMapOS(v unsafe.Pointer, n uintptr) {
199 }
200
201 func sysFaultOS(v unsafe.Pointer, n uintptr) {
202 }
203
204 func sysReserveOS(v unsafe.Pointer, n uintptr) unsafe.Pointer {
205 lock(&memlock)
206 var p unsafe.Pointer
207 if uintptr(v) == bloc {
208
209
210 p = sbrk(n)
211 }
212 if p == nil && v == nil {
213 p = memAlloc(n)
214 memCheck()
215 }
216 unlock(&memlock)
217 return p
218 }
219
220 func sysReserveAlignedSbrk(size, align uintptr) (unsafe.Pointer, uintptr) {
221 lock(&memlock)
222 if p := memAllocNoGrow(size + align); p != nil {
223
224
225 pAligned := alignUp(uintptr(p), align)
226 if startLen := pAligned - uintptr(p); startLen > 0 {
227 memFree(p, startLen)
228 }
229 end := pAligned + size
230 if endLen := (uintptr(p) + size + align) - end; endLen > 0 {
231 memFree(unsafe.Pointer(end), endLen)
232 }
233 memCheck()
234 return unsafe.Pointer(pAligned), size
235 }
236
237
238 p := alignUp(bloc, align)
239 r := sbrk(p + size - bloc)
240 if r == nil {
241 p, size = 0, 0
242 } else if l := p - uintptr(r); l > 0 {
243
244 memFree(r, l)
245 memCheck()
246 }
247 unlock(&memlock)
248 return unsafe.Pointer(p), size
249 }
250
View as plain text