mmap_linux.go raw

   1  //go:build !js
   2  // +build !js
   3  
   4  /*
   5   * SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
   6   * SPDX-License-Identifier: Apache-2.0
   7   */
   8  
   9  package z
  10  
  11  import (
  12  	"os"
  13  	"unsafe"
  14  
  15  	"golang.org/x/sys/unix"
  16  )
  17  
  18  // mmap uses the mmap system call to memory-map a file. If writable is true,
  19  // memory protection of the pages is set so that they may be written to as well.
  20  func mmap(fd *os.File, writable bool, size int64) ([]byte, error) {
  21  	mtype := unix.PROT_READ
  22  	if writable {
  23  		mtype |= unix.PROT_WRITE
  24  	}
  25  	return unix.Mmap(int(fd.Fd()), 0, int(size), mtype, unix.MAP_SHARED)
  26  }
  27  
  28  // munmap unmaps a previously mapped slice.
  29  //
  30  // unix.Munmap maintains an internal list of mmapped addresses, and only calls munmap
  31  // if the address is present in that list. If we use mremap, this list is not updated.
  32  // To bypass this, we call munmap ourselves.
  33  func munmap(data []byte) error {
  34  	if len(data) == 0 || len(data) != cap(data) {
  35  		return unix.EINVAL
  36  	}
  37  	_, _, errno := unix.Syscall(
  38  		unix.SYS_MUNMAP,
  39  		uintptr(unsafe.Pointer(&data[0])),
  40  		uintptr(len(data)),
  41  		0,
  42  	)
  43  	if errno != 0 {
  44  		return errno
  45  	}
  46  	return nil
  47  }
  48  
  49  // madvise uses the madvise system call to give advise about the use of memory
  50  // when using a slice that is memory-mapped to a file. Set the readahead flag to
  51  // false if page references are expected in random order.
  52  func madvise(b []byte, readahead bool) error {
  53  	flags := unix.MADV_NORMAL
  54  	if !readahead {
  55  		flags = unix.MADV_RANDOM
  56  	}
  57  	return unix.Madvise(b, flags)
  58  }
  59  
  60  // msync writes any modified data to persistent storage.
  61  func msync(b []byte) error {
  62  	return unix.Msync(b, unix.MS_SYNC)
  63  }
  64