mmap_windows.go raw

   1  //go:build windows
   2  // +build windows
   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  	"fmt"
  13  	"os"
  14  	"syscall"
  15  	"unsafe"
  16  )
  17  
  18  func mmap(fd *os.File, write bool, size int64) ([]byte, error) {
  19  	protect := syscall.PAGE_READONLY
  20  	access := syscall.FILE_MAP_READ
  21  
  22  	if write {
  23  		protect = syscall.PAGE_READWRITE
  24  		access = syscall.FILE_MAP_WRITE
  25  	}
  26  	fi, err := fd.Stat()
  27  	if err != nil {
  28  		return nil, err
  29  	}
  30  
  31  	// In windows, we cannot mmap a file more than it's actual size.
  32  	// So truncate the file to the size of the mmap.
  33  	if fi.Size() < size {
  34  		if err := fd.Truncate(size); err != nil {
  35  			return nil, fmt.Errorf("truncate: %s", err)
  36  		}
  37  	}
  38  
  39  	// Open a file mapping handle.
  40  	sizelo := uint32(size >> 32)
  41  	sizehi := uint32(size) & 0xffffffff
  42  
  43  	handler, err := syscall.CreateFileMapping(syscall.Handle(fd.Fd()), nil,
  44  		uint32(protect), sizelo, sizehi, nil)
  45  	if err != nil {
  46  		return nil, os.NewSyscallError("CreateFileMapping", err)
  47  	}
  48  
  49  	// Create the memory map.
  50  	addr, err := syscall.MapViewOfFile(handler, uint32(access), 0, 0, uintptr(size))
  51  	if addr == 0 {
  52  		return nil, os.NewSyscallError("MapViewOfFile", err)
  53  	}
  54  
  55  	// Close mapping handle.
  56  	if err := syscall.CloseHandle(syscall.Handle(handler)); err != nil {
  57  		return nil, os.NewSyscallError("CloseHandle", err)
  58  	}
  59  
  60  	// Slice memory layout
  61  	// Copied this snippet from golang/sys package
  62  	var sl = struct {
  63  		addr uintptr
  64  		len  int
  65  		cap  int
  66  	}{addr, int(size), int(size)}
  67  
  68  	// Use unsafe to turn sl into a []byte.
  69  	data := *(*[]byte)(unsafe.Pointer(&sl))
  70  
  71  	return data, nil
  72  }
  73  
  74  func munmap(b []byte) error {
  75  	return syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&b[0])))
  76  }
  77  
  78  func madvise(b []byte, readahead bool) error {
  79  	// Do Nothing. We don’t care about this setting on Windows
  80  	return nil
  81  }
  82  
  83  func msync(b []byte) error {
  84  	// TODO: Figure out how to do msync on Windows.
  85  	return nil
  86  }
  87