github.com/moontrade/unsafe@v0.9.1/memory/rpmalloc/cgo_unsafe.go (about)

     1  //go:build !tinygo && (amd64 || arm64)
     2  
     3  package rpmalloc
     4  
     5  /*
     6  //#cgo darwin,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/lib/darwin_amd64 -L${SRCDIR}/lib/darwin_amd64
     7  #cgo CFLAGS: -I./ -w
     8  #cgo darwin,amd64 LDFLAGS: -ldl -lc -lm
     9  #cgo darwin,arm64 LDFLAGS: -ldl -lc -lm
    10  #cgo darwin,amd64 CFLAGS: -I./ -w
    11  #cgo darwin,arm64 CFLAGS: -I./ -w
    12  //#cgo linux,amd64 CFLAGS: -I${SRCDIR}/src
    13  //#cgo linux,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/lib/linux_amd64 -L${SRCDIR}/lib/linux_amd64
    14  #cgo linux,amd64 LDFLAGS: -ldl -lc -lm
    15  #cgo linux,amd64 CFLAGS: -D_GNU_SOURCE -I./ -w
    16  #cgo linux,arm64 LDFLAGS: -ldl -lc -lm
    17  #cgo linux,arm64 CFLAGS: -D_GNU_SOURCE -I./ -w
    18  #include "rpmalloc.h"
    19  //#include <rpmalloc.h>
    20  #include <stdlib.h>
    21  #include <inttypes.h>
    22  #include <string.h>
    23  
    24  typedef struct {
    25  	size_t size;
    26  	size_t ptr;
    27  } malloc_t;
    28  
    29  void do_malloc(uintptr_t arg0, uintptr_t arg1) {
    30  	malloc_t* args = (malloc_t*)arg0;
    31  	args->ptr = (size_t)malloc((size_t)args->size);
    32  }
    33  void do_free(size_t ptr, size_t arg1, uintptr_t arg2, uintptr_t arg3) {
    34  	free((void*)ptr);
    35  }
    36  
    37  void do_rpmalloc_thread_statistics(uintptr_t arg0, uintptr_t arg1) {
    38  	rpmalloc_thread_statistics((rpmalloc_thread_statistics_t*)(void*)arg0);
    39  }
    40  
    41  void do_rpmalloc_global_statistics(size_t arg0, size_t arg1) {
    42  	rpmalloc_global_statistics((rpmalloc_global_statistics_t*)(void*)arg0);
    43  }
    44  
    45  void do_rpmalloc(size_t arg0, size_t arg1) {
    46  	malloc_t* args = (malloc_t*)arg0;
    47  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    48  }
    49  
    50  void do_rpmalloc_zero(size_t arg0, size_t arg1) {
    51  	malloc_t* args = (malloc_t*)arg0;
    52  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    53  	memset((void*)args->ptr, (int)0, (size_t)args->size);
    54  }
    55  
    56  typedef struct {
    57  	size_t size;
    58  	size_t ptr;
    59  	size_t cap;
    60  } malloc_cap_t;
    61  
    62  void do_rpmalloc_cap(size_t arg0, size_t arg1) {
    63  	malloc_cap_t* args = (malloc_cap_t*)arg0;
    64  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    65  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    66  }
    67  
    68  void do_rpmalloc_zero_cap(size_t arg0, size_t arg1) {
    69  	malloc_cap_t* args = (malloc_cap_t*)arg0;
    70  	args->ptr = (size_t)rpmalloc((size_t)args->size);
    71  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    72  	memset((void*)args->ptr, 0, args->cap);
    73  }
    74  
    75  typedef struct {
    76  	size_t num;
    77  	size_t size;
    78  	size_t ptr;
    79  } calloc_t;
    80  
    81  void do_rpcalloc(size_t arg0, size_t arg1) {
    82  	calloc_t* args = (calloc_t*)(void*)arg0;
    83  	args->ptr = (size_t)rpcalloc(args->num, args->size);
    84  }
    85  
    86  typedef struct {
    87  	size_t num;
    88  	size_t size;
    89  	size_t ptr;
    90  	size_t cap;
    91  } calloc_cap_t;
    92  
    93  void do_rpcalloc_cap(size_t arg0, size_t arg1) {
    94  	calloc_cap_t* args = (calloc_cap_t*)(void*)arg0;
    95  	args->ptr = (size_t)rpcalloc(args->num, args->size);
    96  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
    97  }
    98  
    99  typedef struct {
   100  	size_t ptr;
   101  	size_t size;
   102  	size_t newptr;
   103  } realloc_t;
   104  
   105  void do_rprealloc(size_t arg0, size_t arg1) {
   106  	realloc_t* args = (realloc_t*)(void*)arg0;
   107  	args->newptr = (size_t)rprealloc((void*)args->ptr, args->size);
   108  }
   109  
   110  typedef struct {
   111  	size_t ptr;
   112  	size_t size;
   113  	size_t newptr;
   114  	size_t cap;
   115  } realloc_cap_t;
   116  
   117  void do_rprealloc_cap(size_t arg0, size_t arg1) {
   118  	realloc_cap_t* args = (realloc_cap_t*)(void*)arg0;
   119  	args->newptr = (size_t)rprealloc((void*)args->ptr, args->size);
   120  	args->cap = (size_t)rpmalloc_usable_size((void*)args->newptr);
   121  }
   122  
   123  void do_rpfree(size_t ptr, size_t arg2) {
   124  	rpfree((void*)ptr);
   125  }
   126  
   127  typedef struct {
   128  	size_t ptr;
   129  	size_t size;
   130  } usable_size_t;
   131  
   132  void do_rpmalloc_usable_size(size_t arg0, size_t arg1) {
   133  	usable_size_t* args = (usable_size_t*)arg0;
   134  	args->size = (size_t)rpmalloc_usable_size((void*)args->ptr);
   135  }
   136  
   137  typedef struct {
   138  	size_t ptr;
   139  } heap_acquire_t;
   140  
   141  void do_rpmalloc_heap_acquire(size_t arg0, size_t arg1) {
   142  	heap_acquire_t* args = (heap_acquire_t*)(void*)arg0;
   143  	args->ptr = (size_t)rpmalloc_heap_acquire();
   144  }
   145  
   146  typedef struct {
   147  	size_t ptr;
   148  } heap_release_t;
   149  
   150  void do_rpmalloc_heap_release(size_t arg0, size_t arg1) {
   151  	heap_release_t* args = (heap_release_t*)(void*)arg0;
   152  	rpmalloc_heap_release((rpmalloc_heap_t*)(void*)args->ptr);
   153  }
   154  
   155  typedef struct {
   156  	size_t heap;
   157  	size_t size;
   158  	size_t ptr;
   159  } heap_alloc_t;
   160  
   161  void do_rpmalloc_heap_alloc(size_t arg0, size_t arg1) {
   162  	heap_alloc_t* args = (heap_alloc_t*)(void*)arg0;
   163  	args->ptr = (size_t)rpmalloc_heap_alloc((rpmalloc_heap_t*)(void*)args->heap, args->size);
   164  }
   165  
   166  typedef struct {
   167  	size_t heap;
   168  	size_t size;
   169  	size_t ptr;
   170  	size_t cap;
   171  } heap_alloc_cap_t;
   172  
   173  void do_rpmalloc_heap_alloc_cap(size_t arg0, size_t arg1) {
   174  	heap_alloc_cap_t* args = (heap_alloc_cap_t*)(void*)arg0;
   175  	args->ptr = (size_t)rpmalloc_heap_alloc((rpmalloc_heap_t*)(void*)args->heap, args->size);
   176  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
   177  }
   178  
   179  typedef struct {
   180  	size_t heap;
   181  	size_t num;
   182  	size_t size;
   183  	size_t ptr;
   184  } heap_calloc_t;
   185  
   186  void do_rpmalloc_heap_calloc(size_t arg0, size_t arg1) {
   187  	heap_calloc_t* args = (heap_calloc_t*)(void*)arg0;
   188  	args->ptr = (size_t)rpmalloc_heap_calloc((rpmalloc_heap_t*)(void*)args->heap, args->num, args->size);
   189  }
   190  
   191  typedef struct {
   192  	size_t heap;
   193  	size_t num;
   194  	size_t size;
   195  	size_t ptr;
   196  	size_t cap;
   197  } heap_calloc_cap_t;
   198  
   199  void do_rpmalloc_heap_calloc_cap(size_t arg0, size_t arg1) {
   200  	heap_calloc_cap_t* args = (heap_calloc_cap_t*)(void*)arg0;
   201  	args->ptr = (size_t)rpmalloc_heap_calloc((rpmalloc_heap_t*)(void*)args->heap, args->num, args->size);
   202  	args->cap = (size_t)rpmalloc_usable_size((void*)args->ptr);
   203  }
   204  
   205  typedef struct {
   206  	size_t heap;
   207  	size_t ptr;
   208  	size_t size;
   209  	size_t newptr;
   210  	int flags;
   211  } heap_realloc_t;
   212  
   213  void do_rpmalloc_heap_realloc(size_t arg0, size_t arg1) {
   214  	heap_realloc_t* args = (heap_realloc_t*)(void*)arg0;
   215  	args->newptr = (size_t)rpmalloc_heap_realloc((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr, args->size, args->flags);
   216  }
   217  
   218  typedef struct {
   219  	size_t heap;
   220  	size_t ptr;
   221  	size_t size;
   222  	size_t newptr;
   223  	size_t cap;
   224  	int flags;
   225  } heap_realloc_cap_t;
   226  
   227  void do_rpmalloc_heap_realloc_cap(size_t arg0, size_t arg1) {
   228  	heap_realloc_cap_t* args = (heap_realloc_cap_t*)(void*)arg0;
   229  	args->newptr = (size_t)rpmalloc_heap_realloc((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr, args->size, args->flags);
   230  	args->cap = (size_t)rpmalloc_usable_size((void*)args->newptr);
   231  }
   232  
   233  typedef struct {
   234  	size_t heap;
   235  	size_t ptr;
   236  } heap_free_t;
   237  
   238  void do_rpmalloc_heap_free(size_t arg0, size_t arg1) {
   239  	heap_free_t* args = (heap_free_t*)(void*)arg0;
   240  	rpmalloc_heap_free((rpmalloc_heap_t*)(void*)args->heap, (void*)args->ptr);
   241  }
   242  
   243  typedef struct {
   244  	size_t heap;
   245  } heap_free_all_t;
   246  
   247  void do_rpmalloc_heap_free_all(size_t arg0, size_t arg1) {
   248  	heap_free_all_t* args = (heap_free_all_t*)(void*)arg0;
   249  	rpmalloc_heap_free_all((rpmalloc_heap_t*)(void*)args->heap);
   250  }
   251  */
   252  import "C"
   253  import (
   254  	"github.com/moontrade/unsafe/cgo"
   255  	"unsafe"
   256  )
   257  
   258  // ReadThreadStats get thread statistics
   259  func ReadThreadStats(stats *ThreadStats) {
   260  	cgo.NonBlocking((*byte)(C.rpmalloc_thread_statistics), uintptr(unsafe.Pointer(stats)), 0)
   261  }
   262  
   263  // ReadGlobalStats get global statistics
   264  func ReadGlobalStats(stats *GlobalStats) {
   265  	cgo.NonBlocking((*byte)(C.do_rpmalloc_global_statistics), uintptr(unsafe.Pointer(stats)), 0)
   266  }
   267  
   268  // Malloc allocate a memory block of at least the given size
   269  func StdMalloc(size uintptr) uintptr {
   270  	args := struct {
   271  		size uintptr
   272  		ptr  uintptr
   273  	}{size: size}
   274  	ptr := uintptr(unsafe.Pointer(&args))
   275  	cgo.NonBlocking((*byte)(C.do_malloc), ptr, 0)
   276  	return args.ptr
   277  }
   278  
   279  // Free the given memory block
   280  func StdFree(ptr uintptr) {
   281  	cgo.NonBlocking((*byte)(C.do_free), ptr, 0)
   282  }
   283  
   284  // Malloc allocate a memory block of at least the given size
   285  func Malloc(size uintptr) uintptr {
   286  	args := struct {
   287  		size uintptr
   288  		ptr  uintptr
   289  	}{size: size}
   290  	ptr := uintptr(unsafe.Pointer(&args))
   291  	cgo.NonBlocking((*byte)(C.do_rpmalloc), ptr, 0)
   292  	return args.ptr
   293  }
   294  
   295  // Zero clears n bytes starting at ptr.
   296  //
   297  // Usually you should use typedmemclr. memclrNoHeapPointers should be
   298  // used only when the caller knows that *ptr contains no heap pointers
   299  // because either:
   300  //
   301  // *ptr is initialized memory and its type is pointer-free, or
   302  //
   303  // *ptr is uninitialized memory (e.g., memory that's being reused
   304  // for a new allocation) and hence contains only "junk".
   305  //
   306  // memclrNoHeapPointers ensures that if ptr is pointer-aligned, and n
   307  // is a multiple of the pointer size, then any pointer-aligned,
   308  // pointer-sized portion is cleared atomically. Despite the function
   309  // name, this is necessary because this function is the underlying
   310  // implementation of typedmemclr and memclrHasPointers. See the doc of
   311  // Memmove for more details.
   312  //
   313  // The (CPU-specific) implementations of this function are in memclr_*.s.
   314  //
   315  //go:noescape
   316  //go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
   317  func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
   318  
   319  // Malloc allocate a memory block of at least the given size
   320  func MallocZeroed(size uintptr) uintptr {
   321  	args := struct {
   322  		size uintptr
   323  		ptr  uintptr
   324  	}{size: size}
   325  	ptr := uintptr(unsafe.Pointer(&args))
   326  	cgo.NonBlocking((*byte)(C.do_rpmalloc), ptr, 0)
   327  	// This is faster than memset in C and calloc(1, size)
   328  	memclrNoHeapPointers(unsafe.Pointer(args.ptr), size)
   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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.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  	cgo.NonBlocking((*byte)(C.do_rpmalloc_heap_free_all), p, 0)
   556  }