github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/mem_sbrk.go (about) 1 // Copyright 2023 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 //go:build plan9 || wasm 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 // sorted in ascending order 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 // Address range being freed is at the end of memory, 143 // so record a new lower value for end of memory. 144 // Can't actually shrink address space because segment is shared. 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 // Address hint is the current end of memory, 180 // so try to extend the address space. 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 }