github.com/wencode/hack@v0.2.9/mmap/mmap_windows.go (about)

     1  package mmap
     2  
     3  import (
     4  	"os"
     5  	"sync"
     6  
     7  	"golang.org/x/sys/windows"
     8  )
     9  
    10  type handleinfo struct {
    11  	fd      int
    12  	mapview windows.Handle
    13  }
    14  
    15  var (
    16  	handleLocker sync.Mutex
    17  	handleMap    = make(map[uintptr]*handleinfo)
    18  )
    19  
    20  func addHandle(addr uintptr, fd int, mapview windows.Handle) {
    21  	handleLocker.Lock()
    22  	defer handleLocker.Unlock()
    23  	handleMap[addr] = &handleinfo{fd, mapview}
    24  }
    25  
    26  func removeHandle(addr uintptr) *handleinfo {
    27  	handleLocker.Lock()
    28  	defer handleLocker.Unlock()
    29  	hi, ok := handleMap[addr]
    30  	if !ok {
    31  		return nil
    32  	}
    33  	delete(handleMap, addr)
    34  	return hi
    35  }
    36  
    37  func getHandle(addr uintptr) *handleinfo {
    38  	handleLocker.Lock()
    39  	defer handleLocker.Unlock()
    40  	hi := handleMap[addr]
    41  	return hi
    42  }
    43  
    44  func Mmap(fd, prot, offset, len int) (MapBuf, error) {
    45  	var (
    46  		s_prot        = uint32(windows.PAGE_READONLY)
    47  		desiredAccess = uint32(windows.FILE_MAP_READ)
    48  	)
    49  	switch {
    50  	case prot&COW != 0:
    51  		s_prot = windows.PAGE_WRITECOPY
    52  		desiredAccess = windows.FILE_MAP_COPY
    53  	case prot&RDWR != 0:
    54  		s_prot = windows.PAGE_READWRITE
    55  		dwsiredAccess = windows.FILE_MAP_WRITE
    56  	}
    57  	if prot&EXEC != 0 {
    58  		s_prot <<= 4
    59  		desiredAccess |= windows.FILE_MAP_EXECUTE
    60  	}
    61  
    62  	h, errno := windows.CreateFileMapping(
    63  		windows.Handle(fd),
    64  		nil,
    65  		s_prot,
    66  		0,
    67  		0,
    68  		nil)
    69  	if h == 0 {
    70  		return nil, os.NewSyscallError("CreateFileMapping", errno)
    71  	}
    72  
    73  	addr, errno := windows.MapViewOfFile(
    74  		h,
    75  		desiredAccess,
    76  		uint32(offset>>32),
    77  		uint32(offset&0xFFFFFFFF),
    78  		uintptr(len))
    79  	if addr == 0 {
    80  		windows.CloseHandle(h)
    81  		return nil, os.NewSyscallError("MapViewOfFile", errno)
    82  	}
    83  	addHandle(addr, fd, h)
    84  
    85  	var buf MapBuf
    86  	bh := buf.header()
    87  	bh.Data = addr
    88  	bh.Len = len
    89  	bh.Cap = len
    90  	return buf, nil
    91  }
    92  
    93  func (mb MapBuf) Unmap() error {
    94  	addr := header(mb).Data
    95  	hi := removeHandle(addr)
    96  	if hi == nil {
    97  		return nil
    98  	}
    99  	err := windows.UnmapViewOfFile(addr)
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	errno := windows.CloseHandle(windows.Handle(hi.mapview))
   105  	if errno != nil {
   106  		return os.NewSyscallError("CloseHandle", e)
   107  	}
   108  	return nil
   109  }
   110  
   111  func (mb MapBuf) Mlock() error {
   112  	h := mb.header()
   113  	errno := windows.VirtualLock(h.Data, uintptr(h.Len))
   114  	if errno != nil {
   115  		return os.NewSyscallError("VirtualLock", errno)
   116  	}
   117  	return nil
   118  }
   119  
   120  func (mb MapBuf) Munlock() error {
   121  	h := mb.header()
   122  	errno := windows.VirtualUnlock(h.Data, uintptr(h.Len))
   123  	if errno != nil {
   124  		return os.NewSyscallError("VirtualLock", errno)
   125  	}
   126  	return nil
   127  }
   128  
   129  func (mb MapBuf) Sync() error {
   130  	h := mb.header()
   131  	errno := windows.FlushViewOfFile(addr, uintptr(h.Len))
   132  	if errno != nil {
   133  		return os.NewSyscallError("FlushViewOfFile", errno)
   134  	}
   135  
   136  	hi := getHandle(h.Data)
   137  	if hi {
   138  		return errors.New("invalid address")
   139  	}
   140  
   141  	if errno := windows.FlushFileBuffers(windows.Handle(hi.fd)); errno != nil {
   142  		return os.NewSyscallError("FlushFileBuffers", err)
   143  	}
   144  	return nil
   145  }