gopkg.in/ro-ag/posix.v1@v1.0.6/mmap.go (about)

     1  //go:build darwin || linux
     2  // +build darwin linux
     3  
     4  package posix
     5  
     6  import (
     7  	"sync"
     8  	"unsafe"
     9  )
    10  
    11  // Mmap manager, for use by operating system-specific implementations.
    12  
    13  type mmapper struct {
    14  	sync.Mutex
    15  	active map[*byte][]byte // active mappings; key is last byte in mapping
    16  	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
    17  	munmap func(addr uintptr, length uintptr) error
    18  }
    19  
    20  func (m *mmapper) Mmap(address unsafe.Pointer, length uintptr, prot int, flags int, fd int, offset int64) (data []byte, addr uintptr, err error) {
    21  	if length <= 0 {
    22  		return nil, 0x00, EINVAL
    23  	}
    24  
    25  	// Map the requested memory.
    26  	addr, err = m.mmap(uintptr(address), length, prot, flags, fd, offset)
    27  	if err != nil {
    28  		return nil, 0x00, err
    29  	}
    30  
    31  	// Use unsafe to convert addr into a []byte.
    32  	var b []byte
    33  	hdr := (*_unsafeSlice)(unsafe.Pointer(&b))
    34  	hdr.Data = unsafe.Pointer(addr)
    35  	hdr.Cap = int(length)
    36  	hdr.Len = int(length)
    37  
    38  	// Register mapping in m and return it.
    39  	p := &b[cap(b)-1]
    40  	m.Lock()
    41  	defer m.Unlock()
    42  	m.active[p] = b
    43  	return b, addr, nil
    44  }
    45  
    46  func (m *mmapper) Munmap(data []byte) (err error) {
    47  	if len(data) == 0 || len(data) != cap(data) {
    48  		return EINVAL
    49  	}
    50  
    51  	// Find the base of the mapping.
    52  	p := &data[cap(data)-1]
    53  	m.Lock()
    54  	defer m.Unlock()
    55  	b := m.active[p]
    56  	if b == nil || &b[0] != &data[0] {
    57  		return EINVAL
    58  	}
    59  
    60  	// Unmap the memory and update m.
    61  	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
    62  		return errno
    63  	}
    64  	delete(m.active, p)
    65  	return nil
    66  }
    67  
    68  var mapper = &mmapper{
    69  	active: make(map[*byte][]byte),
    70  	mmap:   mmap,
    71  	munmap: munmap,
    72  }