-
Notifications
You must be signed in to change notification settings - Fork 1
/
mmap_windows.go
73 lines (65 loc) · 1.72 KB
/
mmap_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package fqueue
import (
"errors"
"os"
"sync"
"syscall"
"unsafe"
)
const (
PageSize = 65536
MetaSize = 65536
)
var handleLock sync.Mutex
var handleMap = map[uintptr]syscall.Handle{}
func mmap(fd uintptr, off int64, l, inprot int) (sli []byte, err error) {
flProtect := uint32(syscall.PAGE_READONLY)
dwDesiredAccess := uint32(syscall.FILE_MAP_READ)
switch {
case inprot&WRITE != 0:
flProtect = syscall.PAGE_READWRITE
dwDesiredAccess = syscall.FILE_MAP_WRITE
case inprot&RDWR != 0:
flProtect = syscall.PAGE_READWRITE
dwDesiredAccess = syscall.FILE_MAP_WRITE
}
h, errno := syscall.CreateFileMapping(syscall.Handle(fd), nil, flProtect, 0, uint32(l), nil)
if h == 0 {
return nil, os.NewSyscallError("CreateFileMapping", errno)
}
addr, errno := syscall.MapViewOfFile(h, dwDesiredAccess, uint32(off>>32), uint32(off&0xFFFFFFFF), uintptr(l))
if addr == 0 {
return nil, os.NewSyscallError("MapViewOfFile", errno)
}
handleLock.Lock()
handleMap[addr] = h
handleLock.Unlock()
var header = struct {
d uintptr
l, c int
}{addr, l, l}
sli = *(*[]byte)(unsafe.Pointer(&header))
return sli, nil
}
func msync(addr, len uintptr) error {
errno := syscall.FlushViewOfFile(addr, len)
return os.NewSyscallError("FlushViewOfFile", errno)
}
func unmap(p []byte) error {
addr := uintptr(unsafe.Pointer(&p[0]))
syscall.FlushViewOfFile(addr, uintptr(len(p)))
err := syscall.UnmapViewOfFile(addr)
if err != nil {
return err
}
handleLock.Lock()
defer handleLock.Unlock()
handle, ok := handleMap[addr]
if !ok {
// should be impossible; we would've errored above
return errors.New("unknown base address")
}
delete(handleMap, addr)
e := syscall.CloseHandle(syscall.Handle(handle))
return os.NewSyscallError("CloseHandle", e)
}