github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/fixed/allocator.go (about)

     1  package fixed
     2  
     3  import (
     4  	"errors"
     5  	"syscall"
     6  	"unsafe"
     7  )
     8  
     9  var (
    10  	// ErrOverflow returned if requested buffer number larget then max number.
    11  	ErrOverflow = errors.New("buffer number overflow")
    12  )
    13  
    14  var iovecSize = int(unsafe.Sizeof(syscall.Iovec{}))
    15  
    16  type allocator struct {
    17  	max        int // max number of buffers
    18  	bufferSize int // requested size of the buffer
    19  
    20  	// mem is splitted in two parts
    21  	// header - list of iovec structs.
    22  	// starts at mem[0]. current length is iovecSz*allocated
    23  	// buffers - list of buffers of the same size.
    24  	mem []byte
    25  
    26  	reg BufferRegistry
    27  }
    28  
    29  func (a *allocator) init() error {
    30  	prot := syscall.PROT_READ | syscall.PROT_WRITE
    31  	flags := syscall.MAP_ANON | syscall.MAP_PRIVATE
    32  	size := a.bufferSize * a.max
    33  	mem, err := syscall.Mmap(-1, 0, size, prot, flags)
    34  	if err != nil {
    35  		return err
    36  	}
    37  	a.mem = mem
    38  	iovec := []syscall.Iovec{{Base: &mem[0], Len: uint64(size)}}
    39  	return a.reg.RegisterBuffers(iovec)
    40  }
    41  
    42  func (a *allocator) close() error {
    43  	return syscall.Munmap(a.mem)
    44  }
    45  
    46  func (a *allocator) bufAt(pos int) []byte {
    47  	start := pos * a.bufferSize
    48  	return a.mem[start : start+a.bufferSize]
    49  }