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