github.com/moontrade/nogc@v0.1.7/alloc/rpmalloc/cgo_unsafe.go (about)

     1  //go:build !tinygo && (amd64 || arm64)
     2  // +build !tinygo
     3  // +build amd64 arm64
     4  
     5  package rpmalloc
     6  
     7  /*
     8  #cgo darwin,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/lib/darwin_amd64 -L${SRCDIR}/lib/darwin_amd64
     9  #cgo darwin,amd64 LDFLAGS: -lrpmalloc -ldl -lc -lm
    10  #cgo linux,amd64 CFLAGS: -I${SRCDIR}/src
    11  #cgo linux,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/lib/linux_amd64 -L${SRCDIR}/lib/linux_amd64
    12  #cgo linux,amd64 LDFLAGS: -lrpmalloc -ldl -lc -lm
    13  #cgo linux,amd64 CFLAGS: -D_GNU_SOURCE
    14  #include "rpmalloc.h"
    15  #include <rpmalloc.h>
    16  #include <stdlib.h>
    17  #include <inttypes.h>
    18  #include <string.h>
    19  
    20  typedef struct {
    21  	size_t size;
    22  	size_t ptr;
    23  } malloc_t;
    24  
    25  void do_malloc(uintptr_t arg0, uintptr_t arg1) {
    26  	malloc_t* args = (malloc_t*)arg0;
    27  	args->ptr = (size_t)malloc((size_t)args->size);
    28  }
    29  void do_free(size_t ptr, size_t arg1, uintptr_t arg2, uintptr_t arg3) {
    30  	free((void*)ptr);
    31  }
    32  
    33  void do_rpmalloc_thread_statistics(uintptr_t arg0, uintptr_t arg1) {
    34  	rpmalloc_thread_statistics((rpmalloc_thread_statistics_t*)(void*)arg0);
    35  }
    36  
    37  void do_rpmalloc_global_statistics(size_t arg0, size_t arg1) {
    38  	rpmalloc_global_statistics((rpmalloc_global_statistics_t*)(void*)arg0);
    39  }
    40  
    41  void do_rpmalloc(size_t arg0, size_t arg1) {
    42  	malloc_t* args = (malloc_t*)arg0;
    43  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    44  }
    45  
    46  void do_rpmalloc_zero(size_t arg0, size_t arg1) {
    47  	malloc_t* args = (malloc_t*)arg0;
    48  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    49  	memset((void*)args->ptr, (int)0, (size_t)args->size);
    50  }
    51  
    52  typedef struct {
    53  	size_t size;
    54  	size_t ptr;
    55  	size_t cap;
    56  } malloc_cap_t;
    57  
    58  void do_rpmalloc_cap(size_t arg0, size_t arg1) {
    59  	malloc_cap_t* args = (malloc_cap_t*)arg0;
    60  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    61  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    62  }
    63  
    64  void do_rpmalloc_zero_cap(size_t arg0, size_t arg1) {
    65  	malloc_cap_t* args = (malloc_cap_t*)arg0;
    66  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    67  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    68  	memset((void*)args->ptr, 0, args->cap);
    69  }
    70  
    71  typedef struct {
    72  	size_t num;
    73  	size_t size;
    74  	size_t ptr;
    75  } calloc_t;
    76  
    77  void do_rpcalloc(size_t arg0, size_t arg1) {
    78  	calloc_t* args = (calloc_t*)(void*)arg0;
    79  	args->ptr = (size_t)rpcalloc(args->num, args->size);
    80  }
    81  
    82  typedef struct {
    83  	size_t num;
    84  	size_t size;
    85  	size_t ptr;
    86  	size_t cap;
    87  } calloc_cap_t;
    88  
    89  void do_rpcalloc_cap(size_t arg0, size_t arg1) {
    90  	calloc_cap_t* args = (calloc_cap_t*)(void*)arg0;
    91  	args->ptr = (size_t)rpcalloc(args->num, args->size);
    92  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    93  }
    94  
    95  typedef struct {
    96  	size_t ptr;
    97  	size_t size;
    98  	size_t newptr;
    99  } realloc_t;
   100  
   101  void do_rprealloc(size_t arg0, size_t arg1) {
   102  	realloc_t* args = (realloc_t*)(void*)arg0;
   103  	args->newptr = (size_t)rprealloc((void*)args->ptr, args->size);
   104  }
   105  
   106  typedef struct {
   107  	size_t ptr;
   108  	size_t size;
   109  	size_t newptr;
   110  	size_t cap;
   111  } realloc_cap_t;
   112  
   113  void do_rprealloc_cap(size_t arg0, size_t arg1) {
   114  	realloc_cap_t* args = (realloc_cap_t*)(void*)arg0;
   115  	args->newptr = (size_t)rprealloc((void*)args->ptr, args->size);
   116  	args->cap = (size_t)rpmalloc_usable_size((void*)args->newptr);
   117  }
   118  
   119  void do_rpfree(size_t ptr, size_t arg2) {
   120  	rpfree((void*)ptr);
   121  }
   122  
   123  typedef struct {
   124  	size_t ptr;
   125  	size_t size;
   126  } usable_size_t;
   127  
   128  void do_rpmalloc_usable_size(size_t arg0, size_t arg1) {
   129  	usable_size_t* args = (usable_size_t*)arg0;
   130  	args->size = (size_t)rpmalloc_usable_size((void*)args->ptr);
   131  }
   132  
   133  typedef struct {
   134  	size_t ptr;
   135  } heap_acquire_t;
   136  
   137  void do_rpmalloc_heap_acquire(size_t arg0, size_t arg1) {
   138  	heap_acquire_t* args = (heap_acquire_t*)(void*)arg0;
   139  	args->ptr = (size_t)rpmalloc_heap_acquire();
   140  }
   141  
   142  typedef struct {
   143  	size_t ptr;
   144  } heap_release_t;
   145  
   146  void do_rpmalloc_heap_release(size_t arg0, size_t arg1) {
   147  	heap_release_t* args = (heap_release_t*)(void*)arg0;
   148  	rpmalloc_heap_release((rpmalloc_heap_t*)(void*)args->ptr);
   149  }
   150  
   151  typedef struct {
   152  	size_t heap;
   153  	size_t size;
   154  	size_t ptr;
   155  } heap_alloc_t;
   156  
   157  void do_rpmalloc_heap_alloc(size_t arg0, size_t arg1) {
   158  	heap_alloc_t* args = (heap_alloc_t*)(void*)arg0;
   159  	args->ptr = (size_t)rpmalloc_heap_alloc((rpmalloc_heap_t*)(void*)args->heap, args->size);
   160  }
   161  
   162  typedef struct {
   163  	size_t heap;
   164  	size_t size;
   165  	size_t ptr;
   166  	size_t cap;
   167  } heap_alloc_cap_t;
   168  
   169  void do_rpmalloc_heap_alloc_cap(size_t arg0, size_t arg1) {
   170  	heap_alloc_cap_t* args = (heap_alloc_cap_t*)(void*)arg0;
   171  	args->ptr = (size_t)rpmalloc_heap_alloc((rpmalloc_heap_t*)(void*)args->heap, args->size);
   172  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
   173  }
   174  
   175  typedef struct {
   176  	size_t heap;
   177  	size_t num;
   178  	size_t size;
   179  	size_t ptr;
   180  } heap_calloc_t;
   181  
   182  void do_rpmalloc_heap_calloc(size_t arg0, size_t arg1) {
   183  	heap_calloc_t* args = (heap_calloc_t*)(void*)arg0;
   184  	args->ptr = (size_t)rpmalloc_heap_calloc((rpmalloc_heap_t*)(void*)args->heap, args->num, args->size);
   185  }
   186  
   187  typedef struct {
   188  	size_t heap;
   189  	size_t num;
   190  	size_t size;
   191  	size_t ptr;
   192  	size_t cap;
   193  } heap_calloc_cap_t;
   194  
   195  void do_rpmalloc_heap_calloc_cap(size_t arg0, size_t arg1) {
   196  	heap_calloc_cap_t* args = (heap_calloc_cap_t*)(void*)arg0;
   197  	args->ptr = (size_t)rpmalloc_heap_calloc((rpmalloc_heap_t*)(void*)args->heap, args->num, args->size);
   198  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
   199  }
   200  
   201  typedef struct {
   202  	size_t heap;
   203  	size_t ptr;
   204  	size_t size;
   205  	size_t newptr;
   206  	int flags;
   207  } heap_realloc_t;
   208  
   209  void do_rpmalloc_heap_realloc(size_t arg0, size_t arg1) {
   210  	heap_realloc_t* args = (heap_realloc_t*)(void*)arg0;
   211  	args->newptr = (size_t)rpmalloc_heap_realloc((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr, args->size, args->flags);
   212  }
   213  
   214  typedef struct {
   215  	size_t heap;
   216  	size_t ptr;
   217  	size_t size;
   218  	size_t newptr;
   219  	size_t cap;
   220  	int flags;
   221  } heap_realloc_cap_t;
   222  
   223  void do_rpmalloc_heap_realloc_cap(size_t arg0, size_t arg1) {
   224  	heap_realloc_cap_t* args = (heap_realloc_cap_t*)(void*)arg0;
   225  	args->newptr = (size_t)rpmalloc_heap_realloc((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr, args->size, args->flags);
   226  	args->cap = (size_t)rpmalloc_usable_size((void*)args->newptr);
   227  }
   228  
   229  typedef struct {
   230  	size_t heap;
   231  	size_t ptr;
   232  } heap_free_t;
   233  
   234  void do_rpmalloc_heap_free(size_t arg0, size_t arg1) {
   235  	heap_free_t* args = (heap_free_t*)(void*)arg0;
   236  	rpmalloc_heap_free((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr);
   237  }
   238  
   239  typedef struct {
   240  	size_t heap;
   241  } heap_free_all_t;
   242  
   243  void do_rpmalloc_heap_free_all(size_t arg0, size_t arg1) {
   244  	heap_free_all_t* args = (heap_free_all_t*)(void*)arg0;
   245  	rpmalloc_heap_free_all((rpmalloc_heap_t*)(void*)args->heap);
   246  }
   247  */
   248  import "C"
   249  import (
   250  	"github.com/moontrade/nogc/unsafecgo"
   251  	"unsafe"
   252  )
   253  
   254  // ReadThreadStats get thread statistics
   255  func ReadThreadStats(stats *ThreadStats) {
   256  	unsafecgo.NonBlocking((*byte)(C.rpmalloc_thread_statistics), uintptr(unsafe.Pointer(stats)), 0)
   257  }
   258  
   259  // ReadGlobalStats get global statistics
   260  func ReadGlobalStats(stats *GlobalStats) {
   261  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_global_statistics), uintptr(unsafe.Pointer(stats)), 0)
   262  }
   263  
   264  // Malloc allocate a memory block of at least the given size
   265  func StdMalloc(size uintptr) uintptr {
   266  	args := struct {
   267  		size uintptr
   268  		ptr  uintptr
   269  	}{size: size}
   270  	ptr := uintptr(unsafe.Pointer(&args))
   271  	unsafecgo.NonBlocking((*byte)(C.do_malloc), ptr, 0)
   272  	return args.ptr
   273  }
   274  
   275  // Free the given memory block
   276  func StdFree(ptr uintptr) {
   277  	unsafecgo.NonBlocking((*byte)(C.do_free), ptr, 0)
   278  }
   279  
   280  // Malloc allocate a memory block of at least the given size
   281  func Malloc(size uintptr) uintptr {
   282  	args := struct {
   283  		size uintptr
   284  		ptr  uintptr
   285  	}{size: size}
   286  	ptr := uintptr(unsafe.Pointer(&args))
   287  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc), ptr, 0)
   288  	return args.ptr
   289  }
   290  
   291  // Zero clears n bytes starting at ptr.
   292  //
   293  // Usually you should use typedmemclr. memclrNoHeapPointers should be
   294  // used only when the caller knows that *ptr contains no heap pointers
   295  // because either:
   296  //
   297  // *ptr is initialized memory and its type is pointer-free, or
   298  //
   299  // *ptr is uninitialized memory (e.g., memory that's being reused
   300  // for a new allocation) and hence contains only "junk".
   301  //
   302  // memclrNoHeapPointers ensures that if ptr is pointer-aligned, and n
   303  // is a multiple of the pointer size, then any pointer-aligned,
   304  // pointer-sized portion is cleared atomically. Despite the function
   305  // name, this is necessary because this function is the underlying
   306  // implementation of typedmemclr and memclrHasPointers. See the doc of
   307  // Memmove for more details.
   308  //
   309  // The (CPU-specific) implementations of this function are in memclr_*.s.
   310  //
   311  //go:noescape
   312  //go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
   313  func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
   314  
   315  // Malloc allocate a memory block of at least the given size
   316  func MallocZeroed(size uintptr) uintptr {
   317  	args := struct {
   318  		size uintptr
   319  		ptr  uintptr
   320  	}{size: size}
   321  	ptr := uintptr(unsafe.Pointer(&args))
   322  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc), ptr, 0)
   323  	// This is faster than memset in C and calloc(1, size)
   324  	memclrNoHeapPointers(unsafe.Pointer(args.ptr), size)
   325  	return args.ptr
   326  	//args := malloc_t{size: size}
   327  	//ptr := uintptr(unsafe.Pointer(&args))
   328  	//unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_zero), ptr, 0)
   329  	//return args.ptr
   330  }
   331  
   332  // MallocCap allocate a memory block of at least the given size
   333  func MallocCap(size uintptr) (uintptr, uintptr) {
   334  	args := struct {
   335  		size uintptr
   336  		ptr  uintptr
   337  		cap  uintptr
   338  	}{size: size}
   339  	ptr := uintptr(unsafe.Pointer(&args))
   340  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_cap), ptr, 0)
   341  	return args.ptr, args.cap
   342  }
   343  
   344  // MallocZeroedCap allocate a memory block of at least the given size
   345  func MallocZeroedCap(size uintptr) (uintptr, uintptr) {
   346  	args := struct {
   347  		size uintptr
   348  		ptr  uintptr
   349  		cap  uintptr
   350  	}{size: size}
   351  	ptr := uintptr(unsafe.Pointer(&args))
   352  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_zero_cap), ptr, 0)
   353  	return args.ptr, args.cap
   354  }
   355  
   356  // Calloc Allocates a memory block of at least the given size and zero initialize it.
   357  func Calloc(num, size uintptr) uintptr {
   358  	args := struct {
   359  		num  uintptr
   360  		size uintptr
   361  		ptr  uintptr
   362  	}{
   363  		num:  num,
   364  		size: size,
   365  	}
   366  	ptr := uintptr(unsafe.Pointer(&args))
   367  	unsafecgo.NonBlocking((*byte)(C.do_rpcalloc), ptr, 0)
   368  	return args.ptr
   369  }
   370  
   371  // Calloc Allocates a memory block of at least the given size and zero initialize it.
   372  func CallocCap(num, size uintptr) (uintptr, uintptr) {
   373  	args := struct {
   374  		num  uintptr
   375  		size uintptr
   376  		ptr  uintptr
   377  		cap  uintptr
   378  	}{
   379  		num:  num,
   380  		size: size,
   381  	}
   382  	ptr := uintptr(unsafe.Pointer(&args))
   383  	unsafecgo.NonBlocking((*byte)(C.do_rpcalloc_cap), ptr, 0)
   384  	return args.ptr, args.cap
   385  }
   386  
   387  // Realloc the given block to at least the given size
   388  func Realloc(ptr, size uintptr) uintptr {
   389  	args := struct {
   390  		ptr    uintptr
   391  		size   uintptr
   392  		newptr uintptr
   393  	}{
   394  		ptr:  ptr,
   395  		size: size,
   396  	}
   397  	p := uintptr(unsafe.Pointer(&args))
   398  	unsafecgo.NonBlocking((*byte)(C.do_rprealloc), p, 0)
   399  	return args.newptr
   400  }
   401  
   402  // Realloc the given block to at least the given size
   403  func ReallocCap(ptr, size uintptr) (uintptr, uintptr) {
   404  	args := struct {
   405  		ptr    uintptr
   406  		size   uintptr
   407  		newptr uintptr
   408  		cap    uintptr
   409  	}{
   410  		ptr:  ptr,
   411  		size: size,
   412  	}
   413  	p := uintptr(unsafe.Pointer(&args))
   414  	unsafecgo.NonBlocking((*byte)(C.do_rprealloc_cap), p, 0)
   415  	return args.newptr, args.cap
   416  }
   417  
   418  // UsableSize Query the usable size of the given memory block (from given pointer to the end of block)
   419  func UsableSize(ptr uintptr) uintptr {
   420  	args := struct {
   421  		ptr uintptr
   422  		ret uintptr
   423  	}{ptr: ptr}
   424  	p := uintptr(unsafe.Pointer(&args))
   425  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_usable_size), p, 0)
   426  	return args.ret
   427  }
   428  
   429  // Free the given memory block
   430  func Free(ptr uintptr) {
   431  	unsafecgo.NonBlocking((*byte)(C.do_rpfree), ptr, 0)
   432  }
   433  
   434  func InitThread() {
   435  	C.rpmalloc_thread_initialize()
   436  }
   437  
   438  func AcquireHeap() *Heap {
   439  	args := struct {
   440  		ptr uintptr
   441  	}{}
   442  	ptr := uintptr(unsafe.Pointer(&args))
   443  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_acquire), ptr, 0)
   444  	return (*Heap)(unsafe.Pointer(args.ptr))
   445  }
   446  
   447  func (h *Heap) Release() {
   448  	args := struct {
   449  		heap uintptr
   450  	}{heap: uintptr(unsafe.Pointer(h))}
   451  	ptr := uintptr(unsafe.Pointer(&args))
   452  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_release), ptr, 0)
   453  }
   454  
   455  // Alloc Allocate a memory block of at least the given size using the given heap.
   456  func (h *Heap) Alloc(size uintptr) uintptr {
   457  	args := struct {
   458  		heap uintptr
   459  		size uintptr
   460  		ptr  uintptr
   461  	}{heap: uintptr(unsafe.Pointer(h)), size: size}
   462  	ptr := uintptr(unsafe.Pointer(&args))
   463  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_alloc), ptr, 0)
   464  	return args.ptr
   465  }
   466  
   467  // AllocCap Allocate a memory block of at least the given size using the given heap.
   468  func (h *Heap) AllocCap(size uintptr) (uintptr, uintptr) {
   469  	args := struct {
   470  		heap uintptr
   471  		size uintptr
   472  		ptr  uintptr
   473  		cap  uintptr
   474  	}{heap: uintptr(unsafe.Pointer(h)), size: size}
   475  	ptr := uintptr(unsafe.Pointer(&args))
   476  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_alloc), ptr, 0)
   477  	return args.ptr, args.cap
   478  }
   479  
   480  // Calloc Allocate a memory block of at least the given size using the given heap and zero initialize it.
   481  func (h *Heap) Calloc(num, size uintptr) uintptr {
   482  	args := struct {
   483  		heap uintptr
   484  		num  uintptr
   485  		size uintptr
   486  		ptr  uintptr
   487  	}{heap: uintptr(unsafe.Pointer(h)), num: num, size: size}
   488  	ptr := uintptr(unsafe.Pointer(&args))
   489  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_calloc), ptr, 0)
   490  	return args.ptr
   491  }
   492  
   493  // Calloc Allocate a memory block of at least the given size using the given heap and zero initialize it.
   494  func (h *Heap) CallocCap(num, size uintptr) (uintptr, uintptr) {
   495  	args := struct {
   496  		heap uintptr
   497  		num  uintptr
   498  		size uintptr
   499  		ptr  uintptr
   500  		cap  uintptr
   501  	}{heap: uintptr(unsafe.Pointer(h)), num: num, size: size}
   502  	ptr := uintptr(unsafe.Pointer(&args))
   503  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_calloc_cap), ptr, 0)
   504  	return args.ptr, args.cap
   505  }
   506  
   507  // Realloc Reallocate the given block to at least the given size. The memory block MUST be allocated
   508  // by the same heap given to this function.
   509  func (h *Heap) Realloc(ptr, size uintptr, flags int32) uintptr {
   510  	args := struct {
   511  		heap   uintptr
   512  		ptr    uintptr
   513  		size   uintptr
   514  		newptr uintptr
   515  		flags  int32
   516  	}{heap: uintptr(unsafe.Pointer(h)), ptr: ptr, size: size, flags: flags}
   517  	p := uintptr(unsafe.Pointer(&args))
   518  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_realloc), p, 0)
   519  	return args.newptr
   520  }
   521  
   522  // ReallocCap Reallocate the given block to at least the given size. The memory block MUST be allocated
   523  // by the same heap given to this function.
   524  func (h *Heap) ReallocCap(ptr, size uintptr, flags int32) (uintptr, uintptr) {
   525  	args := struct {
   526  		heap   uintptr
   527  		ptr    uintptr
   528  		size   uintptr
   529  		newptr uintptr
   530  		cap    uintptr
   531  		flags  int32
   532  	}{heap: uintptr(unsafe.Pointer(h)), ptr: ptr, size: size, flags: flags}
   533  	p := uintptr(unsafe.Pointer(&args))
   534  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_realloc_cap), p, 0)
   535  	return args.newptr, args.cap
   536  }
   537  
   538  // Free the given memory block from the given heap. The memory block MUST be allocated
   539  // by the same heap given to this function.
   540  func (h *Heap) Free(ptr uintptr) {
   541  	args := struct {
   542  		heap uintptr
   543  		ptr  uintptr
   544  	}{heap: uintptr(unsafe.Pointer(h)), ptr: ptr}
   545  	p := uintptr(unsafe.Pointer(&args))
   546  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_free), p, 0)
   547  }
   548  
   549  // FreeAll memory allocated by the heap
   550  func (h *Heap) FreeAll() {
   551  	args := struct {
   552  		heap uintptr
   553  	}{heap: uintptr(unsafe.Pointer(h))}
   554  	p := uintptr(unsafe.Pointer(&args))
   555  	unsafecgo.NonBlocking((*byte)(C.do_rpmalloc_heap_free_all), p, 0)
   556  }