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 }