github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/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  const (
    22  	// MaxArrayLen is a safe maximum length for slices on this architecture.
    23  	MaxArrayLen = 1<<31 - 1
    24  )
    25  
    26  // New allocates a slice of size n. The returned slice is from manually managed
    27  // memory and MUST be released by calling Free. Failure to do so will result in
    28  // a memory leak.
    29  func New(n int) []byte {
    30  	if n == 0 {
    31  		return make([]byte, 0)
    32  	}
    33  	// We need to be conscious of the Cgo pointer passing rules:
    34  	//
    35  	//   https://golang.org/cmd/cgo/#hdr-Passing_pointers
    36  	//
    37  	//   ...
    38  	//   Note: the current implementation has a bug. While Go code is permitted
    39  	//   to write nil or a C pointer (but not a Go pointer) to C memory, the
    40  	//   current implementation may sometimes cause a runtime error if the
    41  	//   contents of the C memory appear to be a Go pointer. Therefore, avoid
    42  	//   passing uninitialized C memory to Go code if the Go code is going to
    43  	//   store pointer values in it. Zero out the memory in C before passing it
    44  	//   to Go.
    45  	ptr := C.calloc(C.size_t(n), 1)
    46  	if ptr == nil {
    47  		// NB: throw is like panic, except it guarantees the process will be
    48  		// terminated. The call below is exactly what the Go runtime invokes when
    49  		// it cannot allocate memory.
    50  		throw("out of memory")
    51  	}
    52  	// Interpret the C pointer as a pointer to a Go array, then slice.
    53  	return (*[MaxArrayLen]byte)(unsafe.Pointer(ptr))[:n:n]
    54  }
    55  
    56  // Free frees the specified slice.
    57  func Free(b []byte) {
    58  	if cap(b) != 0 {
    59  		if len(b) == 0 {
    60  			b = b[:cap(b)]
    61  		}
    62  		ptr := unsafe.Pointer(&b[0])
    63  		C.free(ptr)
    64  	}
    65  }