|
Blender
V2.59
|
00001 /* 00002 * $Id: mmap_win.c 36271 2011-04-21 13:11:51Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Andrea Weikert. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #if defined(WIN32) 00036 00037 #include <windows.h> 00038 #include <errno.h> 00039 #include <io.h> 00040 #include <sys/types.h> 00041 #include <stdio.h> 00042 00043 #include "mmap_win.h" 00044 00045 #ifndef FILE_MAP_EXECUTE 00046 //not defined in earlier versions of the Platform SDK (before February 2003) 00047 #define FILE_MAP_EXECUTE 0x0020 00048 #endif 00049 00050 /* copied from BKE_utildefines.h ugh */ 00051 #ifdef __GNUC__ 00052 # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) 00053 #else 00054 # define UNUSED(x) x 00055 #endif 00056 00057 /* --------------------------------------------------------------------- */ 00058 /* local storage definitions */ 00059 /* --------------------------------------------------------------------- */ 00060 /* all memory mapped chunks are put in linked lists */ 00061 typedef struct mmapLink 00062 { 00063 struct mmapLink *next,*prev; 00064 } mmapLink; 00065 00066 typedef struct mmapListBase 00067 { 00068 void *first, *last; 00069 } mmapListBase; 00070 00071 typedef struct MemMap { 00072 struct MemMap *next,*prev; 00073 void *mmap; 00074 HANDLE fhandle; 00075 HANDLE maphandle; 00076 } MemMap; 00077 00078 /* --------------------------------------------------------------------- */ 00079 /* local functions */ 00080 /* --------------------------------------------------------------------- */ 00081 00082 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink); 00083 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink); 00084 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr); 00085 00086 static int mmap_get_prot_flags (int flags); 00087 static int mmap_get_access_flags (int flags); 00088 00089 /* --------------------------------------------------------------------- */ 00090 /* vars */ 00091 /* --------------------------------------------------------------------- */ 00092 volatile static struct mmapListBase _mmapbase; 00093 volatile static struct mmapListBase *mmapbase = &_mmapbase; 00094 00095 00096 /* --------------------------------------------------------------------- */ 00097 /* implementation */ 00098 /* --------------------------------------------------------------------- */ 00099 00100 /* mmap for windows */ 00101 void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset) 00102 { 00103 HANDLE fhandle = INVALID_HANDLE_VALUE; 00104 HANDLE maphandle; 00105 int prot_flags = mmap_get_prot_flags(prot); 00106 int access_flags = mmap_get_access_flags(prot); 00107 MemMap *mm = NULL; 00108 void *ptr = NULL; 00109 00110 if ( flags & MAP_FIXED ) { 00111 return MAP_FAILED; 00112 } 00113 00114 /* 00115 if ( fd == -1 ) { 00116 _set_errno( EBADF ); 00117 return MAP_FAILED; 00118 } 00119 */ 00120 00121 if ( fd != -1 ) { 00122 fhandle = (HANDLE) _get_osfhandle (fd); 00123 } 00124 if ( fhandle == INVALID_HANDLE_VALUE ) { 00125 if (!(flags & MAP_ANONYMOUS)) { 00126 errno = EBADF; 00127 return MAP_FAILED; 00128 } 00129 } else { 00130 if ( !DuplicateHandle( GetCurrentProcess(), fhandle, GetCurrentProcess(), 00131 &fhandle, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { 00132 return MAP_FAILED; 00133 } 00134 } 00135 00136 maphandle = CreateFileMapping(fhandle, NULL, prot_flags, 0, len, NULL); 00137 if ( maphandle == 0 ) { 00138 errno = EBADF; 00139 return MAP_FAILED; 00140 } 00141 00142 ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0); 00143 if ( ptr == NULL ) { 00144 DWORD dwLastErr = GetLastError(); 00145 if ( dwLastErr == ERROR_MAPPED_ALIGNMENT ) 00146 errno=EINVAL; 00147 else 00148 errno=EACCES; 00149 CloseHandle(maphandle); 00150 return MAP_FAILED; 00151 } 00152 00153 mm= (MemMap *)malloc(sizeof(MemMap)); 00154 if (!mm) { 00155 errno=ENOMEM; 00156 } 00157 mm->fhandle = fhandle; 00158 mm->maphandle = maphandle; 00159 mm->mmap = ptr; 00160 mmap_addtail(mmapbase, mm); 00161 00162 return ptr; 00163 } 00164 00165 /* munmap for windows */ 00166 intptr_t munmap(void *ptr, intptr_t UNUSED(size)) 00167 { 00168 MemMap *mm = mmap_findlink(mmapbase, ptr); 00169 if (!mm) { 00170 errno=EINVAL; 00171 return -1; 00172 } 00173 UnmapViewOfFile( mm->mmap ); 00174 CloseHandle( mm->maphandle ); 00175 CloseHandle( mm->fhandle); 00176 mmap_remlink(mmapbase, mm); 00177 free(mm); 00178 return 0; 00179 } 00180 00181 /* --------------------------------------------------------------------- */ 00182 /* local functions */ 00183 /* --------------------------------------------------------------------- */ 00184 00185 static void mmap_addtail(volatile mmapListBase *listbase, void *vlink) 00186 { 00187 struct mmapLink *link= vlink; 00188 00189 if (link == 0) return; 00190 if (listbase == 0) return; 00191 00192 link->next = 0; 00193 link->prev = listbase->last; 00194 00195 if (listbase->last) ((struct mmapLink *)listbase->last)->next = link; 00196 if (listbase->first == 0) listbase->first = link; 00197 listbase->last = link; 00198 } 00199 00200 static void mmap_remlink(volatile mmapListBase *listbase, void *vlink) 00201 { 00202 struct mmapLink *link= vlink; 00203 00204 if (link == 0) return; 00205 if (listbase == 0) return; 00206 00207 if (link->next) link->next->prev = link->prev; 00208 if (link->prev) link->prev->next = link->next; 00209 00210 if (listbase->last == link) listbase->last = link->prev; 00211 if (listbase->first == link) listbase->first = link->next; 00212 } 00213 00214 static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr) 00215 { 00216 MemMap *mm; 00217 00218 if (ptr == 0) return NULL; 00219 if (listbase == 0) return NULL; 00220 00221 mm = (MemMap *)listbase->first; 00222 while (mm) { 00223 if (mm->mmap == ptr) { 00224 return mm; 00225 } 00226 mm = mm->next; 00227 } 00228 return NULL; 00229 } 00230 00231 static int mmap_get_prot_flags (int flags) 00232 { 00233 int prot = PAGE_NOACCESS; 00234 00235 if ( ( flags & PROT_READ ) == PROT_READ ) { 00236 if ( ( flags & PROT_WRITE ) == PROT_WRITE ) { 00237 prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 00238 } else { 00239 prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY; 00240 } 00241 } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) { 00242 prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY; 00243 } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) { 00244 prot = PAGE_EXECUTE_READ; 00245 } 00246 return prot; 00247 } 00248 00249 static int mmap_get_access_flags (int flags) 00250 { 00251 int access = 0; 00252 00253 if ( ( flags & PROT_READ ) == PROT_READ ) { 00254 if ( ( flags & PROT_WRITE ) == PROT_WRITE ) { 00255 access = FILE_MAP_WRITE; 00256 } else { 00257 access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ; 00258 } 00259 } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) { 00260 access = FILE_MAP_COPY; 00261 } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) { 00262 access = FILE_MAP_EXECUTE; 00263 } 00264 return access; 00265 } 00266 00267 00268 #endif // WIN32 00269 00270 00271 00272 00273