Blender  V2.59
mmap_win.c
Go to the documentation of this file.
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