git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/mmdb/mmap_windows.go (about) 1 //go:build windows && !appengine 2 // +build windows,!appengine 3 4 package mmdb 5 6 // Windows support largely borrowed from mmap-go. 7 // 8 // Copyright 2011 Evan Shaw. All rights reserved. 9 // Use of this source code is governed by a BSD-style 10 // license that can be found in the LICENSE file. 11 12 import ( 13 "errors" 14 "os" 15 "reflect" 16 "sync" 17 "unsafe" 18 19 "golang.org/x/sys/windows" 20 ) 21 22 type memoryMap []byte 23 24 // Windows 25 var handleLock sync.Mutex 26 var handleMap = map[uintptr]windows.Handle{} 27 28 func mmap(fd int, length int) (data []byte, err error) { 29 h, errno := windows.CreateFileMapping(windows.Handle(fd), nil, 30 uint32(windows.PAGE_READONLY), 0, uint32(length), nil) 31 if h == 0 { 32 return nil, os.NewSyscallError("CreateFileMapping", errno) 33 } 34 35 addr, errno := windows.MapViewOfFile(h, uint32(windows.FILE_MAP_READ), 0, 36 0, uintptr(length)) 37 if addr == 0 { 38 return nil, os.NewSyscallError("MapViewOfFile", errno) 39 } 40 handleLock.Lock() 41 handleMap[addr] = h 42 handleLock.Unlock() 43 44 m := memoryMap{} 45 dh := m.header() 46 dh.Data = addr 47 dh.Len = length 48 dh.Cap = dh.Len 49 50 return m, nil 51 } 52 53 func (m *memoryMap) header() *reflect.SliceHeader { 54 return (*reflect.SliceHeader)(unsafe.Pointer(m)) 55 } 56 57 func flush(addr, len uintptr) error { 58 errno := windows.FlushViewOfFile(addr, len) 59 return os.NewSyscallError("FlushViewOfFile", errno) 60 } 61 62 func munmap(b []byte) (err error) { 63 m := memoryMap(b) 64 dh := m.header() 65 66 addr := dh.Data 67 length := uintptr(dh.Len) 68 69 flush(addr, length) 70 err = windows.UnmapViewOfFile(addr) 71 if err != nil { 72 return err 73 } 74 75 handleLock.Lock() 76 defer handleLock.Unlock() 77 handle, ok := handleMap[addr] 78 if !ok { 79 // should be impossible; we would've errored above 80 return errors.New("unknown base address") 81 } 82 delete(handleMap, addr) 83 84 e := windows.CloseHandle(windows.Handle(handle)) 85 return os.NewSyscallError("CloseHandle", e) 86 }