merge with/from trunk at r35190
[blender.git] / intern / guardedalloc / intern / mmap_win.c
1 /*
2  * $Id: $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Andrea Weikert.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file guardedalloc/intern/mmap_win.c
31  *  \ingroup MEM
32  */
33
34  
35 #if defined(WIN32)
36
37 #include <windows.h>
38 #include <errno.h>
39 #include <io.h>
40 #include <sys/types.h>
41 #include <stdio.h>
42
43 #include "mmap_win.h"
44
45 #ifndef FILE_MAP_EXECUTE
46 //not defined in earlier versions of the Platform  SDK (before February 2003)
47 #define FILE_MAP_EXECUTE 0x0020
48 #endif
49
50 /* copied from BKE_utildefines.h ugh */
51 #ifdef __GNUC__
52 #  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
53 #else
54 #  define UNUSED(x) x
55 #endif
56
57 /* --------------------------------------------------------------------- */
58 /* local storage definitions                                                    */
59 /* --------------------------------------------------------------------- */
60 /* all memory mapped chunks are put in linked lists */
61 typedef struct mmapLink
62 {
63         struct mmapLink *next,*prev;
64 } mmapLink;
65
66 typedef struct mmapListBase 
67 {
68         void *first, *last;
69 } mmapListBase;
70
71 typedef struct MemMap {
72         struct MemMap *next,*prev;
73         void *mmap;
74         HANDLE fhandle;
75         HANDLE maphandle;
76 } MemMap;
77
78 /* --------------------------------------------------------------------- */
79 /* local functions                                                       */
80 /* --------------------------------------------------------------------- */
81
82 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
83 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
84 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
85
86 static int mmap_get_prot_flags (int flags);
87 static int mmap_get_access_flags (int flags);
88
89 /* --------------------------------------------------------------------- */
90 /* vars                                                                  */
91 /* --------------------------------------------------------------------- */
92 volatile static struct mmapListBase _mmapbase;
93 volatile static struct mmapListBase *mmapbase = &_mmapbase;
94
95
96 /* --------------------------------------------------------------------- */
97 /* implementation                                                        */
98 /* --------------------------------------------------------------------- */
99
100 /* mmap for windows */
101 void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset)
102 {
103         HANDLE fhandle = INVALID_HANDLE_VALUE;
104         HANDLE maphandle;
105         int prot_flags = mmap_get_prot_flags(prot);
106         int access_flags = mmap_get_access_flags(prot);
107         MemMap *mm = NULL;
108         void *ptr = NULL;
109
110         if ( flags & MAP_FIXED ) {
111                 return MAP_FAILED;
112         }
113
114         /*
115         if ( fd == -1 ) {
116                 _set_errno( EBADF );
117         return MAP_FAILED;
118         }
119         */
120
121         if ( fd != -1 ) {
122                 fhandle = (HANDLE) _get_osfhandle (fd);
123         }
124         if ( fhandle == INVALID_HANDLE_VALUE ) {
125                 if (!(flags & MAP_ANONYMOUS)) {
126                         errno = EBADF;
127                         return MAP_FAILED;
128                 }
129         } else {
130                 if ( !DuplicateHandle( GetCurrentProcess(), fhandle, GetCurrentProcess(),
131                                                         &fhandle, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
132                         return MAP_FAILED;
133                 }
134         }
135
136         maphandle = CreateFileMapping(fhandle, NULL, prot_flags, 0, len, NULL);
137         if ( maphandle == 0 ) {
138         errno = EBADF;
139                 return MAP_FAILED;
140     }
141
142         ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
143         if ( ptr == NULL ) {
144                 DWORD dwLastErr = GetLastError();
145                 if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
146                         errno=EINVAL;
147                 else
148                         errno=EACCES;
149                 CloseHandle(maphandle);
150                 return MAP_FAILED;
151         }
152
153         mm= (MemMap *)malloc(sizeof(MemMap));
154         if (!mm) {
155                 errno=ENOMEM;
156         }
157         mm->fhandle = fhandle;
158         mm->maphandle = maphandle;
159         mm->mmap = ptr;
160         mmap_addtail(mmapbase, mm);
161
162     return ptr;
163 }
164
165 /* munmap for windows */
166 intptr_t munmap(void *ptr, intptr_t UNUSED(size))
167 {
168         MemMap *mm = mmap_findlink(mmapbase, ptr);
169         if (!mm) {
170                 errno=EINVAL;
171         return -1; 
172         }
173         UnmapViewOfFile( mm->mmap );
174         CloseHandle( mm->maphandle );
175         CloseHandle( mm->fhandle);
176         mmap_remlink(mmapbase, mm);
177         free(mm);
178     return 0;
179 }
180
181 /* --------------------------------------------------------------------- */
182 /* local functions                                                       */
183 /* --------------------------------------------------------------------- */
184
185 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
186 {
187         struct mmapLink *link= vlink;
188
189         if (link == 0) return;
190         if (listbase == 0) return;
191
192         link->next = 0;
193         link->prev = listbase->last;
194
195         if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
196         if (listbase->first == 0) listbase->first = link;
197         listbase->last = link;
198 }
199
200 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
201 {
202         struct mmapLink *link= vlink;
203
204         if (link == 0) return;
205         if (listbase == 0) return;
206
207         if (link->next) link->next->prev = link->prev;
208         if (link->prev) link->prev->next = link->next;
209
210         if (listbase->last == link) listbase->last = link->prev;
211         if (listbase->first == link) listbase->first = link->next;
212 }
213
214 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
215 {
216         MemMap *mm;
217
218         if (ptr == 0) return NULL;
219         if (listbase == 0) return NULL;
220         
221         mm = (MemMap *)listbase->first;
222         while (mm) {
223                 if (mm->mmap == ptr) {
224                         return mm;
225                 }
226                 mm = mm->next;
227         }
228         return NULL;
229 }
230
231 static int mmap_get_prot_flags (int flags)
232 {
233         int prot = PAGE_NOACCESS;
234
235         if ( ( flags & PROT_READ ) == PROT_READ ) {
236         if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
237             prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
238                 } else {
239                         prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
240                 }
241     } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
242                 prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
243     } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
244         prot = PAGE_EXECUTE_READ;
245     }
246         return prot;
247 }
248
249 static int mmap_get_access_flags (int flags)
250 {
251         int access = 0;
252
253         if ( ( flags & PROT_READ ) == PROT_READ ) {
254         if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
255             access = FILE_MAP_WRITE;
256                 } else {
257                         access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
258                 }
259     } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
260                 access = FILE_MAP_COPY;
261     } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
262         access = FILE_MAP_EXECUTE;
263     }
264         return access;
265 }
266
267
268 #endif // WIN32
269
270
271
272
273