modernc.org/libc@v1.24.1/mem_brk.go (about)

     1  // Copyright 2021 The Libc 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 libc.membrk && !libc.memgrind
     6  // +build libc.membrk,!libc.memgrind
     7  
     8  // This is a debug-only version of the memory handling functions. When a
     9  // program is built with -tags=libc.membrk a simple but safe version of malloc
    10  // and friends is used that works like sbrk(2). Additionally free becomes a
    11  // nop.
    12  
    13  package libc // import "modernc.org/libc"
    14  
    15  import (
    16  	"unsafe"
    17  
    18  	"modernc.org/libc/errno"
    19  	"modernc.org/libc/sys/types"
    20  )
    21  
    22  const (
    23  	heapAlign = 16
    24  	memgrind  = false
    25  )
    26  
    27  var (
    28  	heap     = make([]byte, heapSize)
    29  	heapP    = uintptr(unsafe.Pointer(&heap[heapAlign]))
    30  	heapLast = uintptr(unsafe.Pointer(&heap[heapSize-1]))
    31  )
    32  
    33  // void *malloc(size_t size);
    34  func Xmalloc(t *TLS, n types.Size_t) uintptr {
    35  	if n == 0 {
    36  		return 0
    37  	}
    38  
    39  	allocMu.Lock()
    40  
    41  	defer allocMu.Unlock()
    42  
    43  	n2 := uintptr(n) + uintptrSize // reserve space for recording block size
    44  	p := roundup(heapP, 16)
    45  	if p+uintptr(n2) >= heapLast {
    46  		t.setErrno(errno.ENOMEM)
    47  		return 0
    48  	}
    49  
    50  	heapP = p + uintptr(n2)
    51  	*(*uintptr)(unsafe.Pointer(p - uintptrSize)) = uintptr(n)
    52  	return p
    53  }
    54  
    55  // void *calloc(size_t nmemb, size_t size);
    56  func Xcalloc(t *TLS, n, size types.Size_t) uintptr {
    57  	return Xmalloc(t, n*size)
    58  }
    59  
    60  // void *realloc(void *ptr, size_t size);
    61  func Xrealloc(t *TLS, ptr uintptr, size types.Size_t) uintptr {
    62  	switch {
    63  	case ptr != 0 && size != 0:
    64  		p := Xmalloc(t, size)
    65  		sz0 := UsableSize(ptr)
    66  		if p != 0 {
    67  			copy((*RawMem)(unsafe.Pointer(p))[:size:size], (*RawMem)(unsafe.Pointer(ptr))[:sz0:sz0])
    68  		}
    69  		return p
    70  	case ptr == 0 && size != 0:
    71  		return Xmalloc(t, size)
    72  	}
    73  	return 0
    74  }
    75  
    76  // void free(void *ptr);
    77  func Xfree(t *TLS, p uintptr) {}
    78  
    79  func UsableSize(p uintptr) types.Size_t {
    80  	return types.Size_t(*(*uintptr)(unsafe.Pointer(p - uintptrSize)))
    81  }
    82  
    83  // MemAuditStart locks the memory allocator, initializes and enables memory
    84  // auditing. Finaly it unlocks the memory allocator.
    85  //
    86  // Some memory handling errors, like double free or freeing of unallocated
    87  // memory, will panic when memory auditing is enabled.
    88  //
    89  // This memory auditing functionality has to be enabled using the libc.memgrind
    90  // build tag.
    91  //
    92  // It is intended only for debug/test builds. It slows down memory allocation
    93  // routines and it has additional memory costs.
    94  func MemAuditStart() {}
    95  
    96  // MemAuditReport locks the memory allocator, reports memory leaks, if any.
    97  // Finally it disables memory auditing and unlocks the memory allocator.
    98  //
    99  // This memory auditing functionality has to be enabled using the libc.memgrind
   100  // build tag.
   101  //
   102  // It is intended only for debug/test builds. It slows down memory allocation
   103  // routines and it has additional memory costs.
   104  func MemAuditReport() error { return nil }