github.com/moontrade/nogc@v0.1.7/alloc/tlsf/heap_std.go (about) 1 //go:build !tinygo && !wasm && !wasi && !tinygo.wasm && (darwin || linux) 2 // +build !tinygo 3 // +build !wasm 4 // +build !wasi 5 // +build !tinygo.wasm 6 // +build darwin linux 7 8 package tlsf 9 10 import ( 11 "sync" 12 "unsafe" 13 ) 14 15 func NewHeap(pages int32) *Heap { 16 return NewHeapWithConfig(pages, NewSliceArena(), GrowMin) 17 } 18 19 func NewHeapWithConfig(pages int32, pageAlloc Arena, grow GrowFactory) *Heap { 20 if pages <= 0 { 21 pages = 1 22 } 23 g := grow(pageAlloc) 24 if g == nil { 25 g = GrowMin(pageAlloc) 26 } 27 pagesAdded, start, end := g(0, pages, 0) 28 a := Bootstrap(start, end, pagesAdded, g) 29 a.arena = uintptr(unsafe.Pointer(&pageAlloc)) 30 return a 31 } 32 33 //// Scope creates an Auto free list that automatically reclaims memory 34 //// after callback finishes. 35 //func (a *Heap) Scope(fn func(a Auto)) { 36 // if fn == nil { 37 // return 38 // } 39 // auto := NewAuto(a.As, 32) 40 // defer auto.Free() 41 // fn(auto) 42 //} 43 // 44 //// Scope creates an Auto free list that automatically reclaims memory 45 //// after callback finishes. 46 //func (a *Sync) Scope(fn func(a Auto)) { 47 // if fn == nil { 48 // return 49 // } 50 // auto := NewAuto(a.AsAllocator(), 32) 51 // defer auto.Free() 52 // fn(auto) 53 //} 54 55 type SystemAllocator struct { 56 } 57 58 //// Alloc allocates a block of memory that fits the size provided. 59 //// The allocation IS cleared / zeroed out. 60 //func (SystemAllocator) AllocString(size uintptr) uintptr { 61 // a.Lock() 62 // defer a.Unlock() 63 // return a.a.Alloc(size) 64 //} 65 // 66 //// AllocZeroed allocates a block of memory that fits the size provided. 67 //// The allocation is NOT cleared / zeroed out. 68 //func (SystemAllocator) AllocZeroed(size uintptr) uintptr { 69 // a.Lock() 70 // defer a.Unlock() 71 // return a.a.AllocZeroed(size) 72 //} 73 74 type Sync struct { 75 a *Heap 76 Slot uint8 77 sync.Mutex 78 } 79 80 func (a *Heap) ToSync() *Sync { 81 return &Sync{a: a} 82 } 83 84 func (a *Sync) Stats() Stats { 85 return a.a.Stats 86 } 87 88 // Alloc allocates a block of memory that fits the size provided. 89 // The allocation IS cleared / zeroed out. 90 func (a *Sync) Alloc(size uintptr) uintptr { 91 a.Lock() 92 defer a.Unlock() 93 return a.a.Alloc(size) 94 } 95 96 // AllocZeroed allocates a block of memory that fits the size provided. 97 // The allocation is NOT cleared / zeroed out. 98 func (a *Sync) AllocZeroed(size uintptr) uintptr { 99 a.Lock() 100 defer a.Unlock() 101 return a.a.AllocZeroed(size) 102 } 103 104 // Realloc determines the best way to resize an allocation. 105 // Any extra size added is NOT cleared / zeroed out. 106 func (a *Sync) Realloc(ptr uintptr, size uintptr) uintptr { 107 a.Lock() 108 defer a.Unlock() 109 return uintptr(unsafe.Pointer(a.a.moveBlock(checkUsedBlock(ptr), uintptr(size)))) + BlockOverhead 110 } 111 112 // Free release the allocation back into the free list. 113 func (a *Sync) Free(ptr uintptr) { 114 a.Lock() 115 defer a.Unlock() 116 a.a.freeBlock(checkUsedBlock(ptr)) 117 } 118 119 //// Alloc allocates a block of memory that fits the size provided. 120 //// The allocation IS cleared / zeroed out. 121 //func (a *Sync) AllocString(size uintptr) Bytes { 122 // return newString(a.AsAllocator(), size) 123 //} 124 125 type GrowFactory func(arena Arena) Grow 126 127 func GrowByDouble(arena Arena) Grow { 128 return func(pagesBefore, pagesNeeded int32, minSize uintptr) (pagesAdded int32, start, end uintptr) { 129 if pagesBefore > pagesNeeded { 130 pagesAdded = pagesBefore 131 } else { 132 pagesAdded = pagesNeeded 133 } 134 start, end = arena.Alloc(uintptr(pagesAdded) * PageSize) 135 if start == 0 { 136 pagesAdded = pagesNeeded 137 start, end = arena.Alloc(uintptr(pagesAdded) * PageSize) 138 if start == 0 { 139 return 0, 0, 0 140 } 141 } 142 return 143 } 144 } 145 146 func GrowBy(pages int32, arena Arena) Grow { 147 return func(pagesBefore, pagesNeeded int32, minSize uintptr) (pagesAdded int32, start, end uintptr) { 148 if pages > pagesNeeded { 149 pagesAdded = pages 150 } else { 151 pagesAdded = pagesNeeded 152 } 153 start, end = arena.Alloc(uintptr(pagesAdded) * PageSize) 154 if start == 0 { 155 pagesAdded = pagesNeeded 156 start, end = arena.Alloc(uintptr(pagesAdded) * PageSize) 157 if start == 0 { 158 return 0, 0, 0 159 } 160 } 161 return 162 } 163 } 164 165 func GrowMin(arena Arena) Grow { 166 return func(pagesBefore, pagesNeeded int32, minSize uintptr) (int32, uintptr, uintptr) { 167 start, end := arena.Alloc(uintptr(pagesNeeded) * PageSize) 168 if start == 0 { 169 return 0, 0, 0 170 } 171 return pagesNeeded, start, end 172 } 173 }