rebase: update go-ceph to v0.8.0

Updating go-ceph to v0.8.0.

Signed-off-by: Mudit Agarwal <muagarwa@redhat.com>
This commit is contained in:
Mudit Agarwal
2021-02-10 09:08:18 +05:30
committed by mergify[bot]
parent e6098520d1
commit 32d78c4f7f
24 changed files with 1724 additions and 229 deletions

View File

@ -0,0 +1,62 @@
package cutil
/*
#include <stdlib.h>
#include <string.h>
typedef void* voidptr;
*/
import "C"
import (
"unsafe"
)
const (
// MaxIdx is the maximum index on 32 bit systems
MaxIdx = 1<<31 - 1 // 2GB, max int32 value, should be safe
// PtrSize is the size of a pointer
PtrSize = C.sizeof_voidptr
// SizeTSize is the size of C.size_t
SizeTSize = C.sizeof_size_t
)
// SizeT wraps size_t from C.
type SizeT C.size_t
// This section contains a bunch of types that are basically just
// unsafe.Pointer but have specific types to help "self document" what the
// underlying pointer is really meant to represent.
// CPtr is an unsafe.Pointer to C allocated memory
type CPtr unsafe.Pointer
// CharPtrPtr is an unsafe pointer wrapping C's `char**`.
type CharPtrPtr unsafe.Pointer
// CharPtr is an unsafe pointer wrapping C's `char*`.
type CharPtr unsafe.Pointer
// SizeTPtr is an unsafe pointer wrapping C's `size_t*`.
type SizeTPtr unsafe.Pointer
// FreeFunc is a wrapper around calls to, or act like, C's free function.
type FreeFunc func(unsafe.Pointer)
// Malloc is C.malloc
func Malloc(s SizeT) CPtr { return CPtr(C.malloc(C.size_t(s))) }
// Free is C.free
func Free(p CPtr) { C.free(unsafe.Pointer(p)) }
// CString is C.CString
func CString(s string) CharPtr { return CharPtr((C.CString(s))) }
// CBytes is C.CBytes
func CBytes(b []byte) CPtr { return CPtr(C.CBytes(b)) }
// Memcpy is C.memcpy
func Memcpy(dst, src CPtr, n SizeT) {
C.memcpy(unsafe.Pointer(dst), unsafe.Pointer(src), C.size_t(n))
}

View File

@ -5,74 +5,56 @@ package cutil
#include <sys/uio.h>
*/
import "C"
import (
"unsafe"
)
var iovecSize uintptr
// StructIovecPtr is an unsafe pointer wrapping C's `*struct iovec`.
type StructIovecPtr unsafe.Pointer
// Iovec helps manage struct iovec arrays needed by some C functions.
// Iovec is a slice of iovec structs. Might have allocated C memory, so it must
// be freed with the Free() method.
type Iovec struct {
// cvec represents an array of struct iovec C memory
cvec unsafe.Pointer
// length of the array (in elements)
length int
iovec []C.struct_iovec
sbs []*SyncBuffer
}
// NewIovec creates an Iovec, and underlying C memory, of the specified size.
func NewIovec(l int) *Iovec {
r := &Iovec{
cvec: C.malloc(C.size_t(l) * C.size_t(iovecSize)),
length: l,
const iovecSize = C.sizeof_struct_iovec
// ByteSlicesToIovec creates an Iovec and links it to Go buffers in data.
func ByteSlicesToIovec(data [][]byte) (v Iovec) {
n := len(data)
iovecMem := C.malloc(iovecSize * C.size_t(n))
v.iovec = (*[MaxIdx]C.struct_iovec)(iovecMem)[:n:n]
for i, b := range data {
sb := NewSyncBuffer(CPtr(&v.iovec[i].iov_base), b)
v.sbs = append(v.sbs, sb)
v.iovec[i].iov_len = C.size_t(len(b))
}
return r
return
}
// ByteSlicesToIovec takes a slice of byte slices and returns a new iovec that
// maps the slice data to struct iovec entries.
func ByteSlicesToIovec(data [][]byte) *Iovec {
iov := NewIovec(len(data))
for i := range data {
iov.Set(i, data[i])
// Sync makes sure the slices contain the same as the C buffers
func (v *Iovec) Sync() {
for _, sb := range v.sbs {
sb.Sync()
}
return iov
}
// Pointer returns a StructIovecPtr that represents the C memory of the
// underlying array.
func (v *Iovec) Pointer() StructIovecPtr {
return StructIovecPtr(unsafe.Pointer(v.cvec))
// Pointer returns a pointer to the iovec
func (v *Iovec) Pointer() unsafe.Pointer {
return unsafe.Pointer(&v.iovec[0])
}
// Len returns the number of entries in the Iovec.
// Len returns a pointer to the iovec
func (v *Iovec) Len() int {
return v.length
return len(v.iovec)
}
// Free the C memory in the Iovec.
func (v *Iovec) Free() {
if v.cvec != nil {
C.free(v.cvec)
v.cvec = nil
v.length = 0
for _, sb := range v.sbs {
sb.Release()
}
}
// Set will map the memory of the given byte slice to the iovec at the
// specified position.
func (v *Iovec) Set(i int, buf []byte) {
offset := uintptr(i) * iovecSize
iov := (*C.struct_iovec)(unsafe.Pointer(
uintptr(unsafe.Pointer(v.cvec)) + offset))
iov.iov_base = unsafe.Pointer(&buf[0])
iov.iov_len = C.size_t(len(buf))
}
func init() {
var iovec C.struct_iovec
iovecSize = unsafe.Sizeof(iovec)
if len(v.iovec) != 0 {
C.free(unsafe.Pointer(&v.iovec[0]))
}
v.iovec = nil
}

View File

@ -0,0 +1,79 @@
package cutil
import (
"sync"
"unsafe"
)
// PtrGuard respresents a guarded Go pointer (pointing to memory allocated by Go
// runtime) stored in C memory (allocated by C)
type PtrGuard struct {
// These mutexes will be used as binary semaphores for signalling events from
// one thread to another, which - in contrast to other languages like C++ - is
// possible in Go, that is a Mutex can be locked in one thread and unlocked in
// another.
stored, release sync.Mutex
released bool
}
// WARNING: using binary semaphores (mutexes) for signalling like this is quite
// a delicate task in order to avoid deadlocks or panics. Whenever changing the
// code logic, please review at least three times that there is no unexpected
// state possible. Usually the natural choice would be to use channels instead,
// but these can not easily passed to C code because of the pointer-to-pointer
// cgo rule, and would require the use of a Go object registry.
// NewPtrGuard writes the goPtr (pointing to Go memory) into C memory at the
// position cPtr, and returns a PtrGuard object.
func NewPtrGuard(cPtr CPtr, goPtr unsafe.Pointer) *PtrGuard {
var v PtrGuard
// Since the mutexes are used for signalling, they have to be initialized to
// locked state, so that following lock attempts will block.
v.release.Lock()
v.stored.Lock()
// Start a background go routine that lives until Release is called. This
// calls a special function that makes sure the garbage collector doesn't touch
// goPtr, stores it into C memory at position cPtr and then waits until it
// reveices the "release" signal, after which it nulls out the C memory at
// cPtr and then exits.
go func() {
storeUntilRelease(&v, (*CPtr)(cPtr), uintptr(goPtr))
}()
// Wait for the "stored" signal from the go routine when the Go pointer has
// been stored to the C memory. <--(1)
v.stored.Lock()
return &v
}
// Release removes the guarded Go pointer from the C memory by overwriting it
// with NULL.
func (v *PtrGuard) Release() {
if !v.released {
v.released = true
v.release.Unlock() // Send the "release" signal to the go routine. -->(2)
v.stored.Lock() // Wait for the second "stored" signal when the C memory
// has been nulled out. <--(3)
}
}
//go:uintptrescapes
// From https://golang.org/src/cmd/compile/internal/gc/lex.go:
// For the next function declared in the file any uintptr arguments may be
// pointer values converted to uintptr. This directive ensures that the
// referenced allocated object, if any, is retained and not moved until the call
// completes, even though from the types alone it would appear that the object
// is no longer needed during the call. The conversion to uintptr must appear in
// the argument list.
// Also see https://golang.org/cmd/compile/#hdr-Compiler_Directives
func storeUntilRelease(v *PtrGuard, cPtr *CPtr, goPtr uintptr) {
uip := (*uintptr)(unsafe.Pointer(cPtr))
*uip = goPtr // store Go pointer in C memory at c_ptr
v.stored.Unlock() // send "stored" signal to main thread -->(1)
v.release.Lock() // wait for "release" signal from main thread when
// Release() has been called. <--(2)
*uip = 0 // reset C memory to NULL
v.stored.Unlock() // send second "stored" signal to main thread -->(3)
}

View File

@ -0,0 +1,28 @@
// +build ptrguard
package cutil
import (
"unsafe"
)
// SyncBuffer is a C buffer connected to a data slice
type SyncBuffer struct {
pg *PtrGuard
}
// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr
func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer {
var v SyncBuffer
v.pg = NewPtrGuard(cPtr, unsafe.Pointer(&data[0]))
return &v
}
// Release releases the C buffer and nulls its stored pointer
func (v *SyncBuffer) Release() {
v.pg.Release()
}
// Sync asserts that changes in the C buffer are available in the data
// slice
func (v *SyncBuffer) Sync() {}

View File

@ -0,0 +1,37 @@
// +build !ptrguard
package cutil
// SyncBuffer is a C buffer connected to a data slice
type SyncBuffer struct {
data []byte
cPtr *CPtr
}
// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr
func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer {
var v SyncBuffer
v.data = data
v.cPtr = (*CPtr)(cPtr)
*v.cPtr = CBytes(data)
return &v
}
// Release releases the C buffer and nulls its stored pointer
func (v *SyncBuffer) Release() {
if v.cPtr != nil {
Free(*v.cPtr)
*v.cPtr = nil
v.cPtr = nil
}
v.data = nil
}
// Sync asserts that changes in the C buffer are available in the data
// slice
func (v *SyncBuffer) Sync() {
if v.cPtr == nil {
return
}
Memcpy(CPtr(&v.data[0]), CPtr(*v.cPtr), SizeT(len(v.data)))
}

View File

@ -1,28 +0,0 @@
package cutil
import "C"
import (
"unsafe"
)
// Basic types from C that we can make "public" without too much fuss.
// SizeT wraps size_t from C.
type SizeT C.size_t
// This section contains a bunch of types that are basically just
// unsafe.Pointer but have specific types to help "self document" what the
// underlying pointer is really meant to represent.
// CharPtrPtr is an unsafe pointer wrapping C's `char**`.
type CharPtrPtr unsafe.Pointer
// CharPtr is an unsafe pointer wrapping C's `char*`.
type CharPtr unsafe.Pointer
// SizeTPtr is an unsafe pointer wrapping C's `size_t*`.
type SizeTPtr unsafe.Pointer
// FreeFunc is a wrapper around calls to, or act like, C's free function.
type FreeFunc func(unsafe.Pointer)

View File

@ -28,3 +28,12 @@ func CStructToTimespec(cts CTimespecPtr) Timespec {
Nsec: int64(t.tv_nsec),
}
}
// CopyToCStruct copies the time values from a Timespec to a previously
// allocated C `struct timespec`. Due to restrictions on Cgo the C pointer
// must be passed via the CTimespecPtr wrapper.
func CopyToCStruct(ts Timespec, cts CTimespecPtr) {
t := (*C.struct_timespec)(cts)
t.tv_sec = C.time_t(ts.Sec)
t.tv_nsec = C.long(ts.Nsec)
}