github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/mem_plan9.go (about) 1 // Copyright 2010 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 package runtime 6 7 import "unsafe" 8 9 const memDebug = false 10 11 var bloc uintptr 12 var blocMax uintptr 13 var memlock mutex 14 15 type memHdr struct { 16 next memHdrPtr 17 size uintptr 18 } 19 20 var memFreelist memHdrPtr // sorted in ascending order 21 22 type memHdrPtr uintptr 23 24 func (p memHdrPtr) ptr() *memHdr { return (*memHdr)(unsafe.Pointer(p)) } 25 func (p *memHdrPtr) set(x *memHdr) { *p = memHdrPtr(unsafe.Pointer(x)) } 26 27 func memAlloc(n uintptr) unsafe.Pointer { 28 n = memRound(n) 29 var prevp *memHdr 30 for p := memFreelist.ptr(); p != nil; p = p.next.ptr() { 31 if p.size >= n { 32 if p.size == n { 33 if prevp != nil { 34 prevp.next = p.next 35 } else { 36 memFreelist = p.next 37 } 38 } else { 39 p.size -= n 40 p = (*memHdr)(add(unsafe.Pointer(p), p.size)) 41 } 42 *p = memHdr{} 43 return unsafe.Pointer(p) 44 } 45 prevp = p 46 } 47 return sbrk(n) 48 } 49 50 func memFree(ap unsafe.Pointer, n uintptr) { 51 n = memRound(n) 52 memclrNoHeapPointers(ap, n) 53 bp := (*memHdr)(ap) 54 bp.size = n 55 bpn := uintptr(ap) 56 if memFreelist == 0 { 57 bp.next = 0 58 memFreelist.set(bp) 59 return 60 } 61 p := memFreelist.ptr() 62 if bpn < uintptr(unsafe.Pointer(p)) { 63 memFreelist.set(bp) 64 if bpn+bp.size == uintptr(unsafe.Pointer(p)) { 65 bp.size += p.size 66 bp.next = p.next 67 *p = memHdr{} 68 } else { 69 bp.next.set(p) 70 } 71 return 72 } 73 for ; p.next != 0; p = p.next.ptr() { 74 if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) { 75 break 76 } 77 } 78 if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) { 79 bp.size += p.next.ptr().size 80 bp.next = p.next.ptr().next 81 *p.next.ptr() = memHdr{} 82 } else { 83 bp.next = p.next 84 } 85 if uintptr(unsafe.Pointer(p))+p.size == bpn { 86 p.size += bp.size 87 p.next = bp.next 88 *bp = memHdr{} 89 } else { 90 p.next.set(bp) 91 } 92 } 93 94 func memCheck() { 95 if !memDebug { 96 return 97 } 98 for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() { 99 if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) { 100 print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n") 101 throw("mem: infinite loop") 102 } 103 if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) { 104 print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n") 105 throw("mem: unordered list") 106 } 107 if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) { 108 print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n") 109 throw("mem: overlapping blocks") 110 } 111 for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) { 112 if *(*byte)(b) != 0 { 113 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") 114 throw("mem: uninitialised memory") 115 } 116 } 117 } 118 } 119 120 func memRound(p uintptr) uintptr { 121 return (p + _PAGESIZE - 1) &^ (_PAGESIZE - 1) 122 } 123 124 func initBloc() { 125 bloc = memRound(firstmoduledata.end) 126 blocMax = bloc 127 } 128 129 func sbrk(n uintptr) unsafe.Pointer { 130 // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c 131 bl := bloc 132 n = memRound(n) 133 if bl+n > blocMax { 134 if brk_(unsafe.Pointer(bl+n)) < 0 { 135 return nil 136 } 137 blocMax = bl + n 138 } 139 bloc += n 140 return unsafe.Pointer(bl) 141 } 142 143 func sysAllocOS(n uintptr) unsafe.Pointer { 144 lock(&memlock) 145 p := memAlloc(n) 146 memCheck() 147 unlock(&memlock) 148 return p 149 } 150 151 func sysFreeOS(v unsafe.Pointer, n uintptr) { 152 lock(&memlock) 153 if uintptr(v)+n == bloc { 154 // Address range being freed is at the end of memory, 155 // so record a new lower value for end of memory. 156 // Can't actually shrink address space because segment is shared. 157 memclrNoHeapPointers(v, n) 158 bloc -= n 159 } else { 160 memFree(v, n) 161 memCheck() 162 } 163 unlock(&memlock) 164 } 165 166 func sysUnusedOS(v unsafe.Pointer, n uintptr) { 167 } 168 169 func sysUsedOS(v unsafe.Pointer, n uintptr) { 170 } 171 172 func sysHugePageOS(v unsafe.Pointer, n uintptr) { 173 } 174 175 func sysMapOS(v unsafe.Pointer, n uintptr) { 176 } 177 178 func sysFaultOS(v unsafe.Pointer, n uintptr) { 179 } 180 181 func sysReserveOS(v unsafe.Pointer, n uintptr) unsafe.Pointer { 182 lock(&memlock) 183 var p unsafe.Pointer 184 if uintptr(v) == bloc { 185 // Address hint is the current end of memory, 186 // so try to extend the address space. 187 p = sbrk(n) 188 } 189 if p == nil && v == nil { 190 p = memAlloc(n) 191 memCheck() 192 } 193 unlock(&memlock) 194 return p 195 }