github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/mmap/mmap_linux.go (about) 1 package mmap 2 3 import ( 4 "os" 5 "reflect" 6 "unsafe" 7 8 "golang.org/x/sys/unix" 9 ) 10 11 // mmap uses the mmap system call to memory-map a file. If writable is true, 12 // memory protection of the pages is set so that they may be written to as well. 13 func mmap(fd *os.File, writable bool, size int64) ([]byte, error) { 14 mtype := unix.PROT_READ 15 if writable { 16 mtype |= unix.PROT_WRITE 17 } 18 return unix.Mmap(int(fd.Fd()), 0, int(size), mtype, unix.MAP_SHARED) 19 } 20 21 // mremap is a Linux-specific system call to remap pages in memory. This can be used in place of munmap + mmap. 22 func mremap(data []byte, size int) ([]byte, error) { 23 // taken from <https://github.com/torvalds/linux/blob/f8394f232b1eab649ce2df5c5f15b0e528c92091/include/uapi/linux/mman.h#L8> 24 const MREMAP_MAYMOVE = 0x1 25 26 header := (*reflect.SliceHeader)(unsafe.Pointer(&data)) 27 mmapAddr, _, errno := unix.Syscall6( 28 unix.SYS_MREMAP, 29 header.Data, 30 uintptr(header.Len), 31 uintptr(size), 32 uintptr(MREMAP_MAYMOVE), 33 0, 34 0, 35 ) 36 if errno != 0 { 37 return nil, errno 38 } 39 40 header.Data = mmapAddr 41 header.Cap = size 42 header.Len = size 43 return data, nil 44 } 45 46 // munmap unmaps a previously mapped slice. 47 // 48 // unix.Munmap maintains an internal list of mmapped addresses, and only calls munmap 49 // if the address is present in that list. If we use mremap, this list is not updated. 50 // To bypass this, we call munmap ourselves. 51 func munmap(data []byte) error { 52 if len(data) == 0 || len(data) != cap(data) { 53 return unix.EINVAL 54 } 55 _, _, errno := unix.Syscall( 56 unix.SYS_MUNMAP, 57 uintptr(unsafe.Pointer(&data[0])), 58 uintptr(len(data)), 59 0, 60 ) 61 if errno != 0 { 62 return errno 63 } 64 return nil 65 } 66 67 // madvise uses the madvise system call to give advise about the use of memory 68 // when using a slice that is memory-mapped to a file. Set the readahead flag to 69 // false if page references are expected in random order. 70 func madvise(b []byte, readahead bool) error { 71 flags := unix.MADV_NORMAL 72 if !readahead { 73 flags = unix.MADV_RANDOM 74 } 75 return unix.Madvise(b, flags) 76 } 77 78 // msync writes any modified data to persistent storage. 79 func msync(b []byte) error { 80 return unix.Msync(b, unix.MS_SYNC) 81 }