vocabtree  0.0.1
mmap.hpp
Go to the documentation of this file.
1 /// This file provides a cross platform way of accessing mmap
2 #pragma once
3 #if !defined(WIN32) && defined(UNIX)
4 #include <sys/mman.h>
5 #elif defined(WIN32) && !defined(UNIX)
6 
7 // mmap prot flags
8 #define PROT_NONE 0x00 // no access (not supported on Win32)
9 #define PROT_READ 0x01
10 #define PROT_WRITE 0x02
11 
12 // mmap flags
13 #define MAP_SHARED 0x01 // share changes across processes
14 #define MAP_PRIVATE 0x02 // private copy-on-write mapping
15 #define MAP_FIXED 0x04
16 
17 #define MAP_FAILED 0
18 
19 extern void* mmap(void* start, size_t len, int prot, int flags, int fd, off_t offset);
20 extern int munmap(void* start, size_t len);
21 
22 
23 
24 void* mmap(void* const user_start, const size_t len, const int prot, const int flags, const int fd, const off_t offset) {
25  {
26  WIN_SAVE_LAST_ERROR;
27 
28  // assume fd = -1 (requesting mapping backed by page file),
29  // so that we notice invalid file handles below.
30  HANDLE hFile = INVALID_HANDLE_VALUE;
31  if(fd != -1) {
32  hFile = mk_handle(_get_osfhandle(fd));
33  if(hFile == INVALID_HANDLE_VALUE) {
34  debug_warn("mmap: invalid file handle");
35  goto fail;
36  }
37  }
38 
39  // MapView.. will choose start address unless MAP_FIXED was specified.
40  void* start = 0;
41  if(flags & MAP_FIXED) {
42  start = user_start;
43  if(start == 0) // assert below would fire
44  goto fail;
45  }
46 
47  // figure out access rights.
48  // note: reads are always allowed (Win32 limitation).
49 
50  SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES), (void*)0, FALSE };
51  DWORD flProtect = PAGE_READONLY;
52  DWORD dwAccess = FILE_MAP_READ;
53 
54  // .. no access: not possible on Win32.
55  if(prot == PROT_NONE)
56  goto fail;
57  // .. write or read/write (Win32 doesn't support write-only)
58  if(prot & PROT_WRITE) {
59  flProtect = PAGE_READWRITE;
60 
61  const bool shared = (flags & MAP_SHARED ) != 0;
62  const bool priv = (flags & MAP_PRIVATE) != 0;
63  // .. both aren't allowed
64  if(shared && priv)
65  goto fail;
66  // .. changes are shared & written to file
67  else if(shared)
68  {
69  sec.bInheritHandle = TRUE;
70  dwAccess = FILE_MAP_ALL_ACCESS;
71  }
72  // .. private copy-on-write mapping
73  else if(priv)
74  {
75  flProtect = PAGE_WRITECOPY;
76  dwAccess = FILE_MAP_COPY;
77  }
78  }
79 
80  // now actually map.
81  const DWORD len_hi = (DWORD)((u64)len >> 32);
82  // careful! language doesn't allow shifting 32-bit types by 32 bits.
83  const DWORD len_lo = (DWORD)len & 0xffffffff;
84  const HANDLE hMap = CreateFileMapping(hFile, &sec, flProtect, len_hi, len_lo, (LPCSTR)0);
85  if(hMap == INVALID_HANDLE_VALUE)
86  // bail now so that MapView.. doesn't overwrite the last error value.
87  goto fail;
88  void* ptr = MapViewOfFileEx(hMap, dwAccess, len_hi, offset, len_lo, start);
89 
90  // free the mapping object now, so that we don't have to hold on to its
91  // handle until munmap(). it's not actually released yet due to the
92  // reference held by MapViewOfFileEx (if it succeeded).
93  if(hMap != INVALID_HANDLE_VALUE) // avoid "invalid handle" error
94  CloseHandle(hMap);
95 
96  if(!ptr)
97  // bail now, before the last error value is restored,
98  // but after freeing the mapping object.
99  goto fail;
100 
101  assert(!(flags & MAP_FIXED) || (ptr == start));
102  // fixed => ptr = start
103 
104  WIN_RESTORE_LAST_ERROR;
105 
106  return ptr;
107  }
108 fail:
109  return MAP_FAILED;
110 }
111 
112 
113 int munmap(void* const start, const size_t len) {
114  UNUSED(len);
115  BOOL ok = UnmapViewOfFile(start);
116  return ok? 0 : -1;
117 }
118 
119 #endif