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 }