Source file
src/runtime/mem_sbrk.go
1
2
3
4
5
6
7 package runtime
8
9 import "unsafe"
10
11 const memDebug = false
12
13 var bloc uintptr
14 var blocMax uintptr
15 var memlock mutex
16
17 type memHdr struct {
18 next memHdrPtr
19 size uintptr
20 }
21
22 var memFreelist memHdrPtr
23
24 type memHdrPtr uintptr
25
26 func (p memHdrPtr) ptr() *memHdr { return (*memHdr)(unsafe.Pointer(p)) }
27 func (p *memHdrPtr) set(x *memHdr) { *p = memHdrPtr(unsafe.Pointer(x)) }
28
29 func memAlloc(n uintptr) unsafe.Pointer {
30 n = memRound(n)
31 var prevp *memHdr
32 for p := memFreelist.ptr(); p != nil; p = p.next.ptr() {
33 if p.size >= n {
34 if p.size == n {
35 if prevp != nil {
36 prevp.next = p.next
37 } else {
38 memFreelist = p.next
39 }
40 } else {
41 p.size -= n
42 p = (*memHdr)(add(unsafe.Pointer(p), p.size))
43 }
44 *p = memHdr{}
45 return unsafe.Pointer(p)
46 }
47 prevp = p
48 }
49 return sbrk(n)
50 }
51
52 func memFree(ap unsafe.Pointer, n uintptr) {
53 n = memRound(n)
54 memclrNoHeapPointers(ap, n)
55 bp := (*memHdr)(ap)
56 bp.size = n
57 bpn := uintptr(ap)
58 if memFreelist == 0 {
59 bp.next = 0
60 memFreelist.set(bp)
61 return
62 }
63 p := memFreelist.ptr()
64 if bpn < uintptr(unsafe.Pointer(p)) {
65 memFreelist.set(bp)
66 if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
67 bp.size += p.size
68 bp.next = p.next
69 *p = memHdr{}
70 } else {
71 bp.next.set(p)
72 }
73 return
74 }
75 for ; p.next != 0; p = p.next.ptr() {
76 if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) {
77 break
78 }
79 }
80 if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
81 bp.size += p.next.ptr().size
82 bp.next = p.next.ptr().next
83 *p.next.ptr() = memHdr{}
84 } else {
85 bp.next = p.next
86 }
87 if uintptr(unsafe.Pointer(p))+p.size == bpn {
88 p.size += bp.size
89 p.next = bp.next
90 *bp = memHdr{}
91 } else {
92 p.next.set(bp)
93 }
94 }
95
96 func memCheck() {
97 if !memDebug {
98 return
99 }
100 for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() {
101 if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) {
102 print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n")
103 throw("mem: infinite loop")
104 }
105 if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) {
106 print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n")
107 throw("mem: unordered list")
108 }
109 if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) {
110 print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n")
111 throw("mem: overlapping blocks")
112 }
113 for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) {
114 if *(*byte)(b) != 0 {
115 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")
116 throw("mem: uninitialised memory")
117 }
118 }
119 }
120 }
121
122 func memRound(p uintptr) uintptr {
123 return alignUp(p, physPageSize)
124 }
125
126 func initBloc() {
127 bloc = memRound(firstmoduledata.end)
128 blocMax = bloc
129 }
130
131 func sysAllocOS(n uintptr) unsafe.Pointer {
132 lock(&memlock)
133 p := memAlloc(n)
134 memCheck()
135 unlock(&memlock)
136 return p
137 }
138
139 func sysFreeOS(v unsafe.Pointer, n uintptr) {
140 lock(&memlock)
141 if uintptr(v)+n == bloc {
142
143
144
145 memclrNoHeapPointers(v, n)
146 bloc -= n
147 } else {
148 memFree(v, n)
149 memCheck()
150 }
151 unlock(&memlock)
152 }
153
154 func sysUnusedOS(v unsafe.Pointer, n uintptr) {
155 }
156
157 func sysUsedOS(v unsafe.Pointer, n uintptr) {
158 }
159
160 func sysHugePageOS(v unsafe.Pointer, n uintptr) {
161 }
162
163 func sysNoHugePageOS(v unsafe.Pointer, n uintptr) {
164 }
165
166 func sysHugePageCollapseOS(v unsafe.Pointer, n uintptr) {
167 }
168
169 func sysMapOS(v unsafe.Pointer, n uintptr) {
170 }
171
172 func sysFaultOS(v unsafe.Pointer, n uintptr) {
173 }
174
175 func sysReserveOS(v unsafe.Pointer, n uintptr) unsafe.Pointer {
176 lock(&memlock)
177 var p unsafe.Pointer
178 if uintptr(v) == bloc {
179
180
181 p = sbrk(n)
182 }
183 if p == nil && v == nil {
184 p = memAlloc(n)
185 memCheck()
186 }
187 unlock(&memlock)
188 return p
189 }
190
View as plain text