mmap_windows.go 1.8 KB

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