github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/manual/manual.go (about) 1 // Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package manual 6 7 // #include <stdlib.h> 8 import "C" 9 import ( 10 "unsafe" 11 ) 12 13 // The go:linkname directives provides backdoor access to private functions in 14 // the runtime. Below we're accessing the throw function. 15 16 //go:linkname throw runtime.throw 17 func throw(s string) 18 19 // TODO(peter): Rather than relying an C malloc/free, we could fork the Go 20 // runtime page allocator and allocate large chunks of memory using mmap or 21 // similar. 22 23 // New allocates a slice of size n. The returned slice is from manually managed 24 // memory and MUST be released by calling Free. Failure to do so will result in 25 // a memory leak. 26 func New(n int) []byte { 27 if n == 0 { 28 return make([]byte, 0) 29 } 30 // We need to be conscious of the Cgo pointer passing rules: 31 // 32 // https://golang.org/cmd/cgo/#hdr-Passing_pointers 33 // 34 // ... 35 // Note: the current implementation has a bug. While Go code is permitted 36 // to write nil or a C pointer (but not a Go pointer) to C memory, the 37 // current implementation may sometimes cause a runtime error if the 38 // contents of the C memory appear to be a Go pointer. Therefore, avoid 39 // passing uninitialized C memory to Go code if the Go code is going to 40 // store pointer values in it. Zero out the memory in C before passing it 41 // to Go. 42 ptr := C.calloc(C.size_t(n), 1) 43 if ptr == nil { 44 // NB: throw is like panic, except it guarantees the process will be 45 // terminated. The call below is exactly what the Go runtime invokes when 46 // it cannot allocate memory. 47 throw("out of memory") 48 } 49 // Interpret the C pointer as a pointer to a Go array, then slice. 50 return (*[MaxArrayLen]byte)(unsafe.Pointer(ptr))[:n:n] 51 } 52 53 // Free frees the specified slice. 54 func Free(b []byte) { 55 if cap(b) != 0 { 56 if len(b) == 0 { 57 b = b[:cap(b)] 58 } 59 ptr := unsafe.Pointer(&b[0]) 60 C.free(ptr) 61 } 62 }