github.com/etecs-ru/ristretto@v0.9.1/z/mmap_linux.go (about) 1 /* 2 * Copyright 2020 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package z 18 19 import ( 20 "os" 21 "reflect" 22 "unsafe" 23 24 "golang.org/x/sys/unix" 25 ) 26 27 // mmap uses the mmap system call to memory-map a file. If writable is true, 28 // memory protection of the pages is set so that they may be written to as well. 29 func mmap(fd *os.File, writable bool, size int64) ([]byte, error) { 30 mtype := unix.PROT_READ 31 if writable { 32 mtype |= unix.PROT_WRITE 33 } 34 return unix.Mmap(int(fd.Fd()), 0, int(size), mtype, unix.MAP_SHARED) 35 } 36 37 // mremap is a Linux-specific system call to remap pages in memory. This can be used in place of munmap + mmap. 38 func mremap(data []byte, size int) ([]byte, error) { 39 // taken from <https://github.com/torvalds/linux/blob/f8394f232b1eab649ce2df5c5f15b0e528c92091/include/uapi/linux/mman.h#L8> 40 const MREMAP_MAYMOVE = 0x1 41 42 header := (*reflect.SliceHeader)(unsafe.Pointer(&data)) 43 mmapAddr, _, errno := unix.Syscall6( 44 unix.SYS_MREMAP, 45 header.Data, 46 uintptr(header.Len), 47 uintptr(size), 48 uintptr(MREMAP_MAYMOVE), 49 0, 50 0, 51 ) 52 if errno != 0 { 53 return nil, errno 54 } 55 56 header.Data = mmapAddr 57 header.Cap = size 58 header.Len = size 59 return data, nil 60 } 61 62 // munmap unmaps a previously mapped slice. 63 // 64 // unix.Munmap maintains an internal list of mmapped addresses, and only calls munmap 65 // if the address is present in that list. If we use mremap, this list is not updated. 66 // To bypass this, we call munmap ourselves. 67 func munmap(data []byte) error { 68 if len(data) == 0 || len(data) != cap(data) { 69 return unix.EINVAL 70 } 71 _, _, errno := unix.Syscall( 72 unix.SYS_MUNMAP, 73 uintptr(unsafe.Pointer(&data[0])), 74 uintptr(len(data)), 75 0, 76 ) 77 if errno != 0 { 78 return errno 79 } 80 return nil 81 } 82 83 // madvise uses the madvise system call to give advise about the use of memory 84 // when using a slice that is memory-mapped to a file. Set the readahead flag to 85 // false if page references are expected in random order. 86 func madvise(b []byte, readahead bool) error { 87 flags := unix.MADV_NORMAL 88 if !readahead { 89 flags = unix.MADV_RANDOM 90 } 91 return unix.Madvise(b, flags) 92 } 93 94 // msync writes any modified data to persistent storage. 95 func msync(b []byte) error { 96 return unix.Msync(b, unix.MS_SYNC) 97 }