== mmap for win32 ==
authorAndrea Weikert <elubie@gmx.net>
Tue, 29 Apr 2008 18:41:34 +0000 (18:41 +0000)
committerAndrea Weikert <elubie@gmx.net>
Tue, 29 Apr 2008 18:41:34 +0000 (18:41 +0000)
replacement for mmap/munmap on Windows.
Implemented using CreateFileMapping/MapViewOfFile.

intern/guardedalloc/intern/mallocn.c
intern/guardedalloc/intern/mmap_win.c [new file with mode: 0644]
intern/guardedalloc/make/msvc_7_0/guardedalloc.vcproj
intern/guardedalloc/mmap_win.h [new file with mode: 0644]
source/blender/imbuf/intern/readimage.c
source/blender/makesdna/intern/CMakeLists.txt

index f95d9aa418a176d3728f897cc1318a6d6f565ce3..25f2fd8d26903ef1d7c78bf23eb0a49d865f47de 100644 (file)
 #include <stdarg.h>
 
 /* mmap exception */
-#if defined(AMIGA) || defined(__BeOS) || defined(WIN32)
+#if defined(AMIGA) || defined(__BeOS)
+#elif defined(WIN32)
+#include <sys/types.h>
+#include "mmap_win.h"
 #else
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -289,7 +292,7 @@ void *MEM_callocN(unsigned int len, const char *str)
 /* note; mmap returns zero'd memory */
 void *MEM_mapallocN(unsigned int len, const char *str)
 {
-#if defined(AMIGA) || defined(__BeOS) || defined(WIN32)
+#if defined(AMIGA) || defined(__BeOS)
        return MEM_callocN(len, str);
 #else
        MemHead *memh;
@@ -586,7 +589,7 @@ static void rem_memblock(MemHead *memh)
     totblock--;
     mem_in_use -= memh->len;
    
-#if defined(AMIGA) || defined(__BeOS) || defined(WIN32)
+#if defined(AMIGA) || defined(__BeOS)
     free(memh);
 #else   
    
diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c
new file mode 100644 (file)
index 0000000..cc31cf5
--- /dev/null
@@ -0,0 +1,261 @@
+/**
+ * $Id: $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Andrea Weikert.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#if defined(WIN32)
+
+#include <windows.h>
+#include <errno.h>
+#include <io.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+#include "mmap_win.h"
+
+#ifndef FILE_MAP_EXECUTE
+//not defined in earlier versions of the Platform  SDK (before February 2003)
+#define FILE_MAP_EXECUTE 0x0020
+#endif
+
+/* --------------------------------------------------------------------- */
+/* local storage definitions                                                    */
+/* --------------------------------------------------------------------- */
+/* all memory mapped chunks are put in linked lists */
+typedef struct mmapLink
+{
+       struct mmapLink *next,*prev;
+} mmapLink;
+
+typedef struct mmapListBase 
+{
+       void *first, *last;
+} mmapListBase;
+
+typedef struct MemMap {
+       struct MemMap *next,*prev;
+       void *mmap;
+       HANDLE fhandle;
+       HANDLE maphandle;
+} MemMap;
+
+/* --------------------------------------------------------------------- */
+/* local functions                                                       */
+/* --------------------------------------------------------------------- */
+
+static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
+static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
+static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
+
+static int mmap_get_prot_flags (int flags);
+static int mmap_get_access_flags (int flags);
+
+/* --------------------------------------------------------------------- */
+/* vars                                                                  */
+/* --------------------------------------------------------------------- */
+volatile static struct mmapListBase _mmapbase;
+volatile static struct mmapListBase *mmapbase = &_mmapbase;
+
+
+/* --------------------------------------------------------------------- */
+/* implementation                                                        */
+/* --------------------------------------------------------------------- */
+
+/* mmap for windows */
+void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset)
+{
+       HANDLE fhandle = INVALID_HANDLE_VALUE;
+       HANDLE maphandle;
+       int prot_flags = mmap_get_prot_flags(prot);
+       int access_flags = mmap_get_access_flags(prot);
+       MemMap *mm = NULL;
+       void *ptr = NULL;
+
+       if ( flags & MAP_FIXED ) {
+               return MAP_FAILED;
+       }
+
+       /*
+       if ( fd == -1 ) {
+               _set_errno( EBADF );
+        return MAP_FAILED;
+       }
+       */
+
+       if ( fd != -1 ) {
+               fhandle = (HANDLE) _get_osfhandle (fd);
+       }
+       if ( fhandle == INVALID_HANDLE_VALUE ) {
+               if (!(flags & MAP_ANONYMOUS)) {
+                       errno = EBADF;
+                       return MAP_FAILED;
+               }
+       } else {
+               if ( !DuplicateHandle( GetCurrentProcess(), fhandle, GetCurrentProcess(),
+                                                       &fhandle, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
+                       return MAP_FAILED;
+               }
+       }
+
+       maphandle = CreateFileMapping(fhandle, NULL, prot_flags, 0, len, NULL);
+       if ( maphandle == 0 ) {
+        errno = EBADF;
+               return MAP_FAILED;
+    }
+
+       ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
+       if ( ptr == NULL ) {
+               DWORD dwLastErr = GetLastError();
+               if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
+                       errno=EINVAL;
+               else
+                       errno=EACCES;
+               CloseHandle(maphandle);
+               return MAP_FAILED;
+       }
+
+       mm= (MemMap *)malloc(sizeof(MemMap));
+       if (!mm) {
+               errno=ENOMEM;
+       }
+       mm->fhandle = fhandle;
+       mm->maphandle = maphandle;
+       mm->mmap = ptr;
+       mmap_addtail(mmapbase, mm);
+
+    return ptr;
+}
+
+/* munmap for windows */
+long munmap(void *ptr, long size)
+{
+       MemMap *mm = mmap_findlink(mmapbase, ptr);
+       if (!mm) {
+               errno=EINVAL;
+        return -1; 
+       }
+       UnmapViewOfFile( mm->mmap );
+       CloseHandle( mm->maphandle );
+       CloseHandle( mm->fhandle);
+       mmap_remlink(mmapbase, mm);
+    return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* local functions                                                       */
+/* --------------------------------------------------------------------- */
+
+static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
+{
+       struct mmapLink *link= vlink;
+
+       if (link == 0) return;
+       if (listbase == 0) return;
+
+       link->next = 0;
+       link->prev = listbase->last;
+
+       if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
+       if (listbase->first == 0) listbase->first = link;
+       listbase->last = link;
+}
+
+static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
+{
+       struct mmapLink *link= vlink;
+
+       if (link == 0) return;
+       if (listbase == 0) return;
+
+       if (link->next) link->next->prev = link->prev;
+       if (link->prev) link->prev->next = link->next;
+
+       if (listbase->last == link) listbase->last = link->prev;
+       if (listbase->first == link) listbase->first = link->next;
+}
+
+static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
+{
+       MemMap *mmap_ptr = (MemMap*)ptr;
+       MemMap *mm;
+
+       if (ptr == 0) return NULL;
+       if (listbase == 0) return NULL;
+       
+       mm = (MemMap *)listbase->first;
+       while (mm) {
+               if (mm->mmap == ptr) {
+                       return mm;
+               }
+               mm = mm->next;
+       }
+       return NULL;
+}
+
+static int mmap_get_prot_flags (int flags)
+{
+       int prot = PAGE_NOACCESS;
+
+       if ( ( flags & PROT_READ ) == PROT_READ ) {
+        if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
+            prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+               } else {
+                       prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
+               }
+    } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
+               prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
+    } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
+        prot = PAGE_EXECUTE_READ;
+    }
+       return prot;
+}
+
+static int mmap_get_access_flags (int flags)
+{
+       int access = 0;
+
+       if ( ( flags & PROT_READ ) == PROT_READ ) {
+        if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
+            access = FILE_MAP_WRITE;
+               } else {
+                       access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
+               }
+    } else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
+               access = FILE_MAP_COPY;
+    } else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
+        access = FILE_MAP_EXECUTE;
+    }
+       return access;
+}
+
+
+#endif // WIN32
+
+
+
+
+
index cb3490716fa8947af81cd58ddf0cef6abe75d564..40e88511d5dbf95d06bfdc3aa68df8d98aabb00e 100644 (file)
@@ -251,6 +251,9 @@ ECHO Done
                        <File
                                RelativePath="..\..\intern\mallocn.c">
                        </File>
+                       <File
+                               RelativePath="..\..\intern\mmap_win.c">
+                       </File>
                </Filter>
                <Filter
                        Name="Header Files"
@@ -261,6 +264,13 @@ ECHO Done
                                <File
                                        RelativePath="..\..\MEM_guardedalloc.h">
                                </File>
+                               <File
+                                       RelativePath="..\..\mmap_win.h">
+                               </File>
+                       </Filter>
+                       <Filter
+                               Name="intern"
+                               Filter="">
                        </Filter>
                </Filter>
        </Files>
diff --git a/intern/guardedalloc/mmap_win.h b/intern/guardedalloc/mmap_win.h
new file mode 100644 (file)
index 0000000..f83a2d6
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * $Id: $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Andrea Weikert.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef MMAP_WIN_H
+#define MMAP_WIN_H
+
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+
+#define MAP_FILE 0
+#define MAP_SHARED 1
+#define MAP_PRIVATE 2
+#define MAP_TYPE 0xF
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define MAP_FAILED ((void *)-1)
+
+void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
+long munmap(void *ptr, long size);
+
+#endif
+
index 881fddc1bb2a9f26a755bc6d41ec074f65198ac5..566df53a25e6033ca261bc1a9bfdc7ed25206e0a 100644 (file)
@@ -31,6 +31,9 @@
 
 #ifdef WIN32
 #include <io.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include "mmap_win.h"
 #endif
 
 #include "BLI_blenlib.h"
@@ -229,7 +232,7 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
 
        size = BLI_filesize(file);
 
-#if defined(AMIGA) || defined(__BeOS) || defined(WIN32)
+#if defined(AMIGA) || defined(__BeOS)
        mem= (int *)malloc(size);
        if (mem==0) {
                printf("Out of mem\n");
index d4b222f364451ae3e6c1df7c28a687a5f9d0ea8e..a85f561da92f2e79d481e2261f8bf5d1c76bcdc0 100644 (file)
@@ -24,7 +24,7 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-SET(SRC makesdna.c ../../../../intern/guardedalloc/intern/mallocn.c)
+SET(SRC makesdna.c ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mmap_win.c)
 
 INCLUDE_DIRECTORIES(../../../../intern/guardedalloc ..)