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  }