2nd try to merge sim_physics with trunk rev 19825
[blender.git] / intern / guardedalloc / intern / mmap_win.c
1 /**
2  * $Id: mmap_win.c 19485 2009-03-31 22:34:34Z gsrb3d $
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #if defined(WIN32)
31
32 #include <windows.h>
33 #include <errno.h>
34 #include <io.h>
35 #include <sys/types.h>
36 #include <stdio.h>
37
38 #include "mmap_win.h"
39
40 #ifndef FILE_MAP_EXECUTE
41 //not defined in earlier versions of the Platform  SDK (before February 2003)
42 #define FILE_MAP_EXECUTE 0x0020
43 #endif
44
45 /* --------------------------------------------------------------------- */
46 /* local storage definitions                                                    */
47 /* --------------------------------------------------------------------- */
48 /* all memory mapped chunks are put in linked lists */
49 typedef struct mmapLink
50 {
51         struct mmapLink *next,*prev;
52 } mmapLink;
53
54 typedef struct mmapListBase 
55 {
56         void *first, *last;
57 } mmapListBase;
58
59 typedef struct MemMap {
60         struct MemMap *next,*prev;
61         void *mmap;
62         HANDLE fhandle;
63         HANDLE maphandle;
64 } MemMap;
65
66 /* --------------------------------------------------------------------- */
67 /* local functions                                                       */
68 /* --------------------------------------------------------------------- */
69
70 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
71 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
72 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
73
74 static int mmap_get_prot_flags (int flags);
75 static int mmap_get_access_flags (int flags);
76
77 /* --------------------------------------------------------------------- */
78 /* vars                                                                  */
79 /* --------------------------------------------------------------------- */
80 volatile static struct mmapListBase _mmapbase;
81 volatile static struct mmapListBase *mmapbase = &_mmapbase;
82
83
84 /* --------------------------------------------------------------------- */
85 /* implementation                                                        */
86 /* --------------------------------------------------------------------- */
87
88 /* mmap for windows */
89 void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset)
90 {
91         HANDLE fhandle = INVALID_HANDLE_VALUE;
92         HANDLE maphandle;
93         int prot_flags = mmap_get_prot_flags(prot);
94         int access_flags = mmap_get_access_flags(prot);
95         MemMap *mm = NULL;
96         void *ptr = NULL;
97
98         if ( flags & MAP_FIXED ) {
99                 return MAP_FAILED;
100         }
101
102         /*
103         if ( fd == -1 ) {
104                 _set_errno( EBADF );
105         return MAP_FAILED;
106         }
107         */
108
109         if ( fd != -1 ) {
110                 fhandle = (HANDLE) _get_osfhandle (fd);
111         }
112         if ( fhandle == INVALID_HANDLE_VALUE ) {
113                 if (!(flags & MAP_ANONYMOUS)) {
114                         errno = EBADF;
115                         return MAP_FAILED;
116                 }
117         } else {
118                 if ( !DuplicateHandle( GetCurrentProcess(), fhandle, GetCurrentProcess(),
119                                                         &fhandle, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
120                         return MAP_FAILED;
121                 }
122         }
123
124         maphandle = CreateFileMapping(fhandle, NULL, prot_flags, 0, len, NULL);
125         if ( maphandle == 0 ) {
126         errno = EBADF;
127                 return MAP_FAILED;
128     }
129
130         ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
131         if ( ptr == NULL ) {
132                 DWORD dwLastErr = GetLastError();
133                 if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
134                         errno=EINVAL;
135                 else
136                         errno=EACCES;
137                 CloseHandle(maphandle);
138                 return MAP_FAILED;
139         }
140
141         mm= (MemMap *)malloc(sizeof(MemMap));
142         if (!mm) {
143                 errno=ENOMEM;
144         }
145         mm->fhandle = fhandle;
146         mm->maphandle = maphandle;
147         mm->mmap = ptr;
148         mmap_addtail(mmapbase, mm);
149
150     return ptr;
151 }
152
153 /* munmap for windows */
154 intptr_t munmap(void *ptr, intptr_t size)
155 {
156         MemMap *mm = mmap_findlink(mmapbase, ptr);
157         if (!mm) {
158                 errno=EINVAL;
159         return -1; 
160         }
161         UnmapViewOfFile( mm->mmap );
162         CloseHandle( mm->maphandle );
163         CloseHandle( mm->fhandle);
164         mmap_remlink(mmapbase, mm);
165     return 0;
166 }
167
168 /* --------------------------------------------------------------------- */
169 /* local functions                                                       */
170 /* --------------------------------------------------------------------- */
171
172 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
173 {
174         struct mmapLink *link= vlink;
175
176         if (link == 0) return;
177         if (listbase == 0) return;
178
179         link->next = 0;
180         link->prev = listbase->last;
181
182         if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
183         if (listbase->first == 0) listbase->first = link;
184         listbase->last = link;
185 }
186
187 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
188 {
189         struct mmapLink *link= vlink;
190
191         if (link == 0) return;
192         if (listbase == 0) return;
193
194         if (link->next) link->next->prev = link->prev;
195         if (link->prev) link->prev->next = link->next;
196
197         if (listbase->last == link) listbase->last = link->prev;
198         if (listbase->first == link) listbase->first = link->next;
199 }
200
201 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
202 {
203         MemMap *mm;
204
205         if (ptr == 0) return NULL;
206         if (listbase == 0) return NULL;
207         
208         mm = (MemMap *)listbase->first;
209         while (mm) {
210                 if (mm->mmap == ptr) {
211                         return mm;
212                 }
213                 mm = mm->next;
214         }
215         return NULL;
216 }
217
218 static int mmap_get_prot_flags (int flags)
219 {
220         int prot = PAGE_NOACCESS;
221
222         if ( ( flags & PROT_READ ) == PROT_READ ) {
223         if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
224             prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
225                 } else {
226                         prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
227                 }
228     } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
229                 prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
230     } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
231         prot = PAGE_EXECUTE_READ;
232     }
233         return prot;
234 }
235
236 static int mmap_get_access_flags (int flags)
237 {
238         int access = 0;
239
240         if ( ( flags & PROT_READ ) == PROT_READ ) {
241         if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
242             access = FILE_MAP_WRITE;
243                 } else {
244                         access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
245                 }
246     } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
247                 access = FILE_MAP_COPY;
248     } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
249         access = FILE_MAP_EXECUTE;
250     }
251         return access;
252 }
253
254
255 #endif // WIN32
256
257
258
259
260