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 }