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
52
53
54
55
56
57
58
59
60
61 func memAlloc(n uintptr) unsafe.Pointer {
62 if p := memAllocNoGrow(n); p != nil {
63 return p
64 }
65 return sbrk(n)
66 }
67
68
69
70
71
72
73
74
75
76
77 func memAllocNoGrow(n uintptr) unsafe.Pointer {
78 n = memRound(n)
79 var prevp *memHdr
80 for p := memFreelist.ptr(); p != nil; p = p.next.ptr() {
81 if p.size >= n {
82 if p.size == n {
83 if prevp != nil {
84 prevp.next = p.next
85 } else {
86 memFreelist = p.next
87 }
88 } else {
89 p.size -= n
90 p = (*memHdr)(add(unsafe.Pointer(p), p.size))
91 }
92 *p = memHdr{}
93 return unsafe.Pointer(p)
94 }
95 prevp = p
96 }
97 return nil
98 }
99
100
101
102
103
104
105
106
107
108
109 func memFree(ap unsafe.Pointer, n uintptr) {
110 n = memRound(n)
111 memclrNoHeapPointers(ap, n)
112 bp := (*memHdr)(ap)
113 bp.size = n
114 bpn := uintptr(ap)
115 if memFreelist == 0 {
116 bp.next = 0
117 memFreelist.set(bp)
118 return
119 }
120 p := memFreelist.ptr()
121 if bpn < uintptr(unsafe.Pointer(p)) {
122 memFreelist.set(bp)
123 if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
124 bp.size += p.size
125 bp.next = p.next
126 *p = memHdr{}
127 } else {
128 bp.next.set(p)
129 }
130 return
131 }
132 for ; p.next != 0; p = p.next.ptr() {
133 if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) {
134 break
135 }
136 }
137 if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
138 bp.size += p.next.ptr().size
139 bp.next = p.next.ptr().next
140 *p.next.ptr() = memHdr{}
141 } else {
142 bp.next = p.next
143 }
144 if uintptr(unsafe.Pointer(p))+p.size == bpn {
145 p.size += bp.size
146 p.next = bp.next
147 *bp = memHdr{}
148 } else {
149 p.next.set(bp)
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162 func memCheck() {
163 if !memDebug {
164 return
165 }
166 for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() {
167 if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) {
168 print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n")
169 throw("mem: infinite loop")
170 }
171 if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) {
172 print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n")
173 throw("mem: unordered list")
174 }
175 if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) {
176 print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n")
177 throw("mem: overlapping blocks")
178 }
179 for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) {
180 if *(*byte)(b) != 0 {
181 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")
182 throw("mem: uninitialised memory")
183 }
184 }
185 }
186 }
187
188 func memRound(p uintptr) uintptr {
189 return alignUp(p, physPageSize)
190 }
191
192 func initBloc() {
193 bloc = memRound(firstmoduledata.end)
194 blocMax = bloc
195 }
196
197 func sysAllocOS(n uintptr, _ string) unsafe.Pointer {
198 var p uintptr
199 systemstack(func() {
200 lock(&memlock)
201 p = uintptr(memAlloc(n))
202 memCheck()
203 unlock(&memlock)
204 })
205 return unsafe.Pointer(p)
206 }
207
208 func sysFreeOS(v unsafe.Pointer, n uintptr) {
209 if v == nil {
210
211 return
212 }
213 systemstack(func() {
214 lock(&memlock)
215 if uintptr(v)+n == bloc {
216
217
218
219 memclrNoHeapPointers(v, n)
220 bloc -= n
221 } else {
222 memFree(v, n)
223 memCheck()
224 }
225 unlock(&memlock)
226 })
227 }
228
229 func sysUnusedOS(v unsafe.Pointer, n uintptr) {
230 }
231
232 func sysUsedOS(v unsafe.Pointer, n uintptr) {
233 }
234
235 func sysHugePageOS(v unsafe.Pointer, n uintptr) {
236 }
237
238 func sysNoHugePageOS(v unsafe.Pointer, n uintptr) {
239 }
240
241 func sysHugePageCollapseOS(v unsafe.Pointer, n uintptr) {
242 }
243
244 func sysMapOS(v unsafe.Pointer, n uintptr, _ string) {
245 }
246
247 func sysFaultOS(v unsafe.Pointer, n uintptr) {
248 }
249
250 func sysReserveOS(v unsafe.Pointer, n uintptr, _ string) unsafe.Pointer {
251 var p uintptr
252 systemstack(func() {
253 lock(&memlock)
254 if uintptr(v) == bloc {
255
256
257 p = uintptr(sbrk(n))
258 }
259 if p == 0 && v == nil {
260 p = uintptr(memAlloc(n))
261 memCheck()
262 }
263 unlock(&memlock)
264 })
265 return unsafe.Pointer(p)
266 }
267
268 func sysReserveAlignedSbrk(size, align uintptr) (unsafe.Pointer, uintptr) {
269 var p uintptr
270 systemstack(func() {
271 lock(&memlock)
272 if base := memAllocNoGrow(size + align); base != nil {
273
274
275 start := alignUp(uintptr(base), align)
276 if startLen := start - uintptr(base); startLen > 0 {
277 memFree(base, startLen)
278 }
279 end := start + size
280 if endLen := (uintptr(base) + size + align) - end; endLen > 0 {
281 memFree(unsafe.Pointer(end), endLen)
282 }
283 memCheck()
284 unlock(&memlock)
285 p = start
286 return
287 }
288
289
290 p = alignUp(bloc, align)
291 r := sbrk(p + size - bloc)
292 if r == nil {
293 p, size = 0, 0
294 } else if l := p - uintptr(r); l > 0 {
295
296 memFree(r, l)
297 memCheck()
298 }
299 unlock(&memlock)
300 })
301 return unsafe.Pointer(p), size
302 }
303
304 func needZeroAfterSysUnusedOS() bool {
305 return true
306 }
307
View as plain text