Added mmap.
This commit is contained in:
parent
003921c2d5
commit
21b522df41
95
mmap/mmap.go
Normal file
95
mmap/mmap.go
Normal file
@ -0,0 +1,95 @@
|
||||
package mt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Map creates a memory map of the given file.
|
||||
func Map(
|
||||
prot int, // Memory protection bitmask. See syscall.PROT_* flags.
|
||||
flags int, // See syscall.MAP_* flags. MAP_SHARED is usually fine.
|
||||
length int64,
|
||||
f *os.File,
|
||||
) (
|
||||
[]byte,
|
||||
error,
|
||||
) {
|
||||
|
||||
addr, _, errno := syscall.Syscall6(
|
||||
syscall.SYS_MMAP,
|
||||
0, // addr: 0 => allow kernel to choose
|
||||
uintptr(length),
|
||||
uintptr(prot),
|
||||
uintptr(flags),
|
||||
f.Fd(),
|
||||
0) // offset: 0 => start of file
|
||||
if errno != 0 {
|
||||
return nil, syscall.Errno(errno)
|
||||
}
|
||||
|
||||
var b []byte
|
||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
hdr.Data = addr
|
||||
hdr.Cap = int(length)
|
||||
hdr.Len = 0
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Unmap unmaps the data obtained by Map.
|
||||
func Unmap(data []byte) error {
|
||||
_, _, errno := syscall.Syscall(
|
||||
syscall.SYS_MUNMAP,
|
||||
uintptr(unsafe.Pointer(&data[:1][0])),
|
||||
uintptr(cap(data)),
|
||||
0)
|
||||
if errno != 0 {
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remap truncates the file to `newSize` and returns a new memory map for the
|
||||
// file.
|
||||
func Remap(
|
||||
f *os.File,
|
||||
data []byte,
|
||||
newSize int64,
|
||||
) ([]byte, error) {
|
||||
const mRemapMayMove = 0x1
|
||||
|
||||
if err := f.Truncate(newSize); err != nil {
|
||||
return data, err
|
||||
}
|
||||
|
||||
addr, size, errno := unix.Syscall6(
|
||||
unix.SYS_MREMAP,
|
||||
uintptr(unsafe.Pointer(&data[:1][0])),
|
||||
uintptr(cap(data)),
|
||||
uintptr(newSize),
|
||||
uintptr(mRemapMayMove),
|
||||
0,
|
||||
0)
|
||||
|
||||
if errno != 0 {
|
||||
return data, syscall.Errno(errno)
|
||||
}
|
||||
|
||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
||||
hdr.Data = addr
|
||||
hdr.Cap = int(newSize)
|
||||
hdr.Len = int(newSize)
|
||||
|
||||
if int64(size) != newSize {
|
||||
panic(fmt.Sprintf("mremap returned incorrect size %d != %d",
|
||||
size, newSize))
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user