github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/mmap.go (about)

     1  // +build !windows
     2  
     3  package util
     4  
     5  import (
     6  	"os"
     7  	"syscall"
     8  	"unsafe"
     9  
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  // Mmap uses the mmap system call to memory-map a file. If writable is true,
    14  // memory protection of the pages is set so that they may be written to as well.
    15  func Mmap(fd *os.File, writable bool, size int64) ([]byte, error) {
    16  	mtype := unix.PROT_READ
    17  	if writable {
    18  		mtype |= unix.PROT_WRITE
    19  	}
    20  	return unix.Mmap(int(fd.Fd()), 0, int(size), mtype, unix.MAP_SHARED)
    21  }
    22  
    23  // Munmap unmaps a previously mapped slice.
    24  func Munmap(b []byte) error {
    25  	return unix.Munmap(b)
    26  }
    27  
    28  // Madvise uses the madvise system call to give advise about the use of memory
    29  // when using a slice that is memory-mapped to a file. Set the readahead flag to
    30  // false if page references are expected in random order.
    31  func Madvise(b []byte, readahead bool) error {
    32  	flags := unix.MADV_NORMAL
    33  	if !readahead {
    34  		flags = unix.MADV_RANDOM
    35  	}
    36  	return madvise(b, flags)
    37  }
    38  
    39  // This is required because the unix package does not support the madvise system call on OS X.
    40  func madvise(b []byte, advice int) (err error) {
    41  	_, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])),
    42  		uintptr(len(b)), uintptr(advice))
    43  	if e1 != 0 {
    44  		err = e1
    45  	}
    46  	return
    47  }
    48  
    49  // MSync for flush mmaped bytes
    50  func MSync(b []byte, length int64, flags int) (err error) {
    51  	_, _, e1 := syscall.Syscall(syscall.SYS_MSYNC,
    52  		uintptr(unsafe.Pointer(&b[0])), uintptr(length), uintptr(flags))
    53  	if e1 != 0 {
    54  		err = e1
    55  	}
    56  
    57  	return
    58  }
    59  
    60  // MLock mmaped bytes
    61  func MLock(b []byte, length int) (err error) {
    62  	_, _, e1 := syscall.Syscall(syscall.SYS_MLOCK,
    63  		uintptr(unsafe.Pointer(&b[0])), uintptr(length), 0)
    64  	if e1 != 0 {
    65  		err = e1
    66  	}
    67  
    68  	return
    69  }
    70  
    71  // MUnlock mmaped bytes
    72  func MUnlock(b []byte, length int) (err error) {
    73  	_, _, e1 := syscall.Syscall(syscall.SYS_MUNLOCK,
    74  		uintptr(unsafe.Pointer(&b[0])), uintptr(length), 0)
    75  	if e1 != 0 {
    76  		err = e1
    77  	}
    78  
    79  	return
    80  }