github.com/aloncn/graphics-go@v0.0.1/src/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 memlock mutex 13 14 type memHdr struct { 15 next memHdrPtr 16 size uintptr 17 } 18 19 var memFreelist memHdrPtr // sorted in ascending order 20 21 type memHdrPtr uintptr 22 23 func (p memHdrPtr) ptr() *memHdr { return (*memHdr)(unsafe.Pointer(p)) } 24 func (p *memHdrPtr) set(x *memHdr) { *p = memHdrPtr(unsafe.Pointer(x)) } 25 26 func memAlloc(n uintptr) unsafe.Pointer { 27 n = memRound(n) 28 var prevp *memHdr 29 for p := memFreelist.ptr(); p != nil; p = p.next.ptr() { 30 if p.size >= n { 31 if p.size == n { 32 if prevp != nil { 33 prevp.next = p.next 34 } else { 35 memFreelist = p.next 36 } 37 } else { 38 p.size -= n 39 p = (*memHdr)(add(unsafe.Pointer(p), p.size)) 40 } 41 memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})) 42 return unsafe.Pointer(p) 43 } 44 prevp = p 45 } 46 return sbrk(n) 47 } 48 49 func memFree(ap unsafe.Pointer, n uintptr) { 50 n = memRound(n) 51 memclr(ap, n) 52 bp := (*memHdr)(ap) 53 bp.size = n 54 bpn := uintptr(ap) 55 if memFreelist == 0 { 56 bp.next = 0 57 memFreelist.set(bp) 58 return 59 } 60 p := memFreelist.ptr() 61 if bpn < uintptr(unsafe.Pointer(p)) { 62 memFreelist.set(bp) 63 if bpn+bp.size == uintptr(unsafe.Pointer(p)) { 64 bp.size += p.size 65 bp.next = p.next 66 memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})) 67 } else { 68 bp.next.set(p) 69 } 70 return 71 } 72 for ; p.next != 0; p = p.next.ptr() { 73 if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) { 74 break 75 } 76 } 77 if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) { 78 bp.size += p.next.ptr().size 79 bp.next = p.next.ptr().next 80 memclr(unsafe.Pointer(p.next), unsafe.Sizeof(memHdr{})) 81 } else { 82 bp.next = p.next 83 } 84 if uintptr(unsafe.Pointer(p))+p.size == bpn { 85 p.size += bp.size 86 p.next = bp.next 87 memclr(unsafe.Pointer(bp), unsafe.Sizeof(memHdr{})) 88 } else { 89 p.next.set(bp) 90 } 91 } 92 93 func memCheck() { 94 if memDebug == false { 95 return 96 } 97 for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() { 98 if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) { 99 print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n") 100 throw("mem: infinite loop") 101 } 102 if uintptr(unsafe.Pointer(p)) > uintptr(unsafe.Pointer(p.next)) { 103 print("runtime: ", unsafe.Pointer(p), " > ", unsafe.Pointer(p.next), "\n") 104 throw("mem: unordered list") 105 } 106 if uintptr(unsafe.Pointer(p))+p.size > uintptr(unsafe.Pointer(p.next)) { 107 print("runtime: ", unsafe.Pointer(p), "+", p.size, " > ", unsafe.Pointer(p.next), "\n") 108 throw("mem: overlapping blocks") 109 } 110 for b := add(unsafe.Pointer(p), unsafe.Sizeof(memHdr{})); uintptr(b) < uintptr(unsafe.Pointer(p))+p.size; b = add(b, 1) { 111 if *(*byte)(b) != 0 { 112 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") 113 throw("mem: uninitialised memory") 114 } 115 } 116 } 117 } 118 119 func memRound(p uintptr) uintptr { 120 return (p + _PAGESIZE - 1) &^ (_PAGESIZE - 1) 121 } 122 123 func initBloc() { 124 bloc = memRound(firstmoduledata.end) 125 } 126 127 func sbrk(n uintptr) unsafe.Pointer { 128 // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c 129 bl := bloc 130 n = memRound(n) 131 if brk_(unsafe.Pointer(bl+n)) < 0 { 132 return nil 133 } 134 bloc += n 135 return unsafe.Pointer(bl) 136 } 137 138 func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer { 139 lock(&memlock) 140 p := memAlloc(n) 141 memCheck() 142 unlock(&memlock) 143 if p != nil { 144 mSysStatInc(sysStat, n) 145 } 146 return p 147 } 148 149 func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) { 150 mSysStatDec(sysStat, n) 151 lock(&memlock) 152 memFree(v, n) 153 memCheck() 154 unlock(&memlock) 155 } 156 157 func sysUnused(v unsafe.Pointer, n uintptr) { 158 } 159 160 func sysUsed(v unsafe.Pointer, n uintptr) { 161 } 162 163 func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) { 164 // sysReserve has already allocated all heap memory, 165 // but has not adjusted stats. 166 mSysStatInc(sysStat, n) 167 } 168 169 func sysFault(v unsafe.Pointer, n uintptr) { 170 } 171 172 func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { 173 *reserved = true 174 lock(&memlock) 175 p := memAlloc(n) 176 memCheck() 177 unlock(&memlock) 178 return p 179 }