Merge pull request #377 from pcercuei/libretro
[pcsx_rearmed.git] / deps / mman / mman.c
1
2 #include <windows.h>
3 #include <errno.h>
4 #include <io.h>
5
6 #include "mman.h"
7
8 #ifndef FILE_MAP_EXECUTE
9 #define FILE_MAP_EXECUTE    0x0020
10 #endif /* FILE_MAP_EXECUTE */
11
12 static int __map_mman_error(const DWORD err, const int deferr)
13 {
14     if (err == 0)
15         return 0;
16     //TODO: implement
17     return err;
18 }
19
20 static DWORD __map_mmap_prot_page(const int prot)
21 {
22     DWORD protect = 0;
23     
24     if (prot == PROT_NONE)
25         return protect;
26         
27     if ((prot & PROT_EXEC) != 0)
28     {
29         protect = ((prot & PROT_WRITE) != 0) ? 
30                     PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
31     }
32     else
33     {
34         protect = ((prot & PROT_WRITE) != 0) ?
35                     PAGE_READWRITE : PAGE_READONLY;
36     }
37     
38     return protect;
39 }
40
41 static DWORD __map_mmap_prot_file(const int prot)
42 {
43     DWORD desiredAccess = 0;
44     
45     if (prot == PROT_NONE)
46         return desiredAccess;
47         
48     if ((prot & PROT_READ) != 0)
49         desiredAccess |= FILE_MAP_READ;
50     if ((prot & PROT_WRITE) != 0)
51         desiredAccess |= FILE_MAP_WRITE;
52     if ((prot & PROT_EXEC) != 0)
53         desiredAccess |= FILE_MAP_EXECUTE;
54     
55     return desiredAccess;
56 }
57
58 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off)
59 {
60     HANDLE fm, h;
61     
62     void * map = MAP_FAILED;
63     
64 #ifdef _MSC_VER
65 #pragma warning(push)
66 #pragma warning(disable: 4293)
67 #endif
68
69     const DWORD dwFileOffsetLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
70                     (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
71     const DWORD dwFileOffsetHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
72                     (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
73     const DWORD protect = __map_mmap_prot_page(prot);
74     const DWORD desiredAccess = __map_mmap_prot_file(prot);
75
76     const OffsetType maxSize = off + (OffsetType)len;
77
78     const DWORD dwMaxSizeLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
79                     (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
80     const DWORD dwMaxSizeHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
81                     (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
82
83 #ifdef _MSC_VER
84 #pragma warning(pop)
85 #endif
86
87     errno = 0;
88     
89     if (len == 0 
90         /* Usupported protection combinations */
91         || prot == PROT_EXEC)
92     {
93         errno = EINVAL;
94         return MAP_FAILED;
95     }
96     
97     h = ((flags & MAP_ANONYMOUS) == 0) ? 
98                     (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
99
100     if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
101     {
102         errno = EBADF;
103         return MAP_FAILED;
104     }
105
106     fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
107
108     if (fm == NULL)
109     {
110         errno = __map_mman_error(GetLastError(), EPERM);
111         return MAP_FAILED;
112     }
113   
114     if ((flags & MAP_FIXED) == 0)
115     {
116         map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
117     }
118     else
119     {
120         map = MapViewOfFileEx(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len, addr);
121     }
122
123     CloseHandle(fm);
124   
125     if (map == NULL)
126     {
127         errno = __map_mman_error(GetLastError(), EPERM);
128         return MAP_FAILED;
129     }
130
131     return map;
132 }
133
134 int munmap(void *addr, size_t len)
135 {
136     if (UnmapViewOfFile(addr))
137         return 0;
138         
139     errno =  __map_mman_error(GetLastError(), EPERM);
140     
141     return -1;
142 }
143
144 int _mprotect(void *addr, size_t len, int prot)
145 {
146     DWORD newProtect = __map_mmap_prot_page(prot);
147     DWORD oldProtect = 0;
148     
149     if (VirtualProtect(addr, len, newProtect, &oldProtect))
150         return 0;
151     
152     errno =  __map_mman_error(GetLastError(), EPERM);
153     
154     return -1;
155 }
156
157 int msync(void *addr, size_t len, int flags)
158 {
159     if (FlushViewOfFile(addr, len))
160         return 0;
161     
162     errno =  __map_mman_error(GetLastError(), EPERM);
163     
164     return -1;
165 }
166
167 int mlock(const void *addr, size_t len)
168 {
169     if (VirtualLock((LPVOID)addr, len))
170         return 0;
171         
172     errno =  __map_mman_error(GetLastError(), EPERM);
173     
174     return -1;
175 }
176
177 int munlock(const void *addr, size_t len)
178 {
179     if (VirtualUnlock((LPVOID)addr, len))
180         return 0;
181         
182     errno =  __map_mman_error(GetLastError(), EPERM);
183     
184     return -1;
185 }