1
2
3
4
5
6
7 package mmap
8
9 import (
10 "fmt"
11 "io/fs"
12 "os"
13 "syscall"
14 )
15
16 func mmapFile(f *os.File) (*Data, error) {
17 st, err := f.Stat()
18 if err != nil {
19 return nil, err
20 }
21 size := st.Size()
22 pagesize := int64(os.Getpagesize())
23 if int64(int(size+(pagesize-1))) != size+(pagesize-1) {
24 return nil, fmt.Errorf("%s: too large for mmap", f.Name())
25 }
26 n := int(size)
27 if n == 0 {
28 return &Data{f, nil, nil}, nil
29 }
30 mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize)
31 data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
32 if err != nil {
33 return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err}
34 }
35 return &Data{f, data[:n], nil}, nil
36 }
37
38 func munmapFile(d *Data) error {
39 if len(d.Data) == 0 {
40 return nil
41 }
42 err := syscall.Munmap(d.Data)
43 if err != nil {
44 return &fs.PathError{Op: "munmap", Path: d.f.Name(), Err: err}
45 }
46 return nil
47 }
48
View as plain text