changeset 21187:d9cedf7b8069

added mmap_anon to osdep lib. Used in loader for now
author nplourde
date Sat, 25 Nov 2006 01:22:20 +0000
parents d3b66895640c
children 4906844e35c8
files Makefile loader/ext.c loader/ldt_keeper.c osdep/Makefile osdep/mmap_anon.c osdep/mmap_anon.h
diffstat 6 files changed, 104 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sat Nov 25 00:50:43 2006 +0000
+++ b/Makefile	Sat Nov 25 01:22:20 2006 +0000
@@ -62,7 +62,6 @@
               stream/stream.a \
               libswscale/libswscale.a \
               libvo/libosd.a \
-              osdep/libosdep.a \
 
 LIBS_MPLAYER = libvo/libvo.a \
                libao2/libao2.a \
@@ -158,6 +157,8 @@
 OBJS_MPLAYER += osdep/mplayer-rc.o
 endif
 
+COMMON_LIBS += osdep/libosdep.a
+
 COMMON_LDFLAGS += $(EXTRA_LIB)\
                   $(EXTRALIBS) \
 
--- a/loader/ext.c	Sat Nov 25 00:50:43 2006 +0000
+++ b/loader/ext.c	Sat Nov 25 01:22:20 2006 +0000
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 #include <ctype.h>
 
+#include "osdep/mmap_anon.h"
 #include "wine/windef.h"
 #include "wine/winbase.h"
 #include "wine/debugtools.h"
@@ -233,7 +234,6 @@
 
 //#define MAP_PRIVATE
 //#define MAP_SHARED
-#undef MAP_ANON
 LPVOID FILE_dommap( int unix_handle, LPVOID start,
                     DWORD size_high, DWORD size_low,
                     DWORD offset_high, DWORD offset_low,
@@ -248,36 +248,15 @@
 
     if (unix_handle == -1)
     {
-#ifdef MAP_ANON
-//	printf("Anonymous\n");
-        flags |= MAP_ANON;
-#else
-        static int fdzero = -1;
+        ret = mmap_anon( start, size_low, prot, flags, &fd, offset_low );
+    }
+    else 
+    {
+        fd = unix_handle;
+        ret = mmap( start, size_low, prot, flags, fd, offset_low );
+    }
 
-        if (fdzero == -1)
-        {
-            if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
-            {
-    		perror( "Cannot open /dev/zero for READ. Check permissions! error: " );
-                exit(1);
-            }
-        }
-        fd = fdzero;
-#endif  /* MAP_ANON */
-	/* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
-#ifdef MAP_SHARED
-	flags &= ~MAP_SHARED;
-#endif
-#ifdef MAP_PRIVATE
-	flags |= MAP_PRIVATE;
-#endif
-    }
-    else fd = unix_handle;
-//    printf("fd %x, start %x, size %x, pos %x, prot %x\n",fd,start,size_low, offset_low, prot);
-//    if ((ret = mmap( start, size_low, prot,
-//                     flags, fd, offset_low )) != (LPVOID)-1)
-    if ((ret = mmap( start, size_low, prot,
-                     MAP_PRIVATE | MAP_FIXED, fd, offset_low )) != (LPVOID)-1)
+    if (ret != (LPVOID)-1)
     {
 //	    printf("address %08x\n", *(int*)ret);
 //	printf("%x\n", ret);
@@ -371,14 +350,8 @@
     int anon=0;
     int mmap_access=0;
     if(hFile<0)
-    {
-	anon=1;
-	hFile=open("/dev/zero", O_RDWR);
-	if(hFile<0){
-    	    perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
-	    return 0;
-	}
-    }
+        anon=1;
+
     if(!anon)
     {
         len=lseek(hFile, 0, SEEK_END);
@@ -391,8 +364,12 @@
     else
 	mmap_access |=PROT_READ|PROT_WRITE;
 
-    answer=mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0);
     if(anon)
+        answer=mmap_anon(NULL, len, mmap_access, MAP_PRIVATE, &hFile, 0);
+    else
+        answer=mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0);
+
+    if(hFile != -1)
         close(hFile);
     if(answer!=(LPVOID)-1)
     {
@@ -418,7 +395,7 @@
 	    fm->name=NULL;
 	fm->mapping_size=len;
 
-	if(anon)
+	if(hFile != -1)
 	    close(hFile);
 	return (HANDLE)answer;
     }
@@ -471,12 +448,6 @@
 
     if ((type&(MEM_RESERVE|MEM_COMMIT)) == 0) return NULL;
 
-    fd=open("/dev/zero", O_RDWR);
-    if(fd<0){
-        perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
-	return NULL;
-    }
-
     if (type&MEM_RESERVE && (unsigned)address&0xffff) {
 	size += (unsigned)address&0xffff;
 	address = (unsigned)address&~0xffff;
@@ -513,23 +484,23 @@
 		   && ((unsigned)address+size<=(unsigned)str->address+str->mapping_size)
 		   && (type & MEM_COMMIT))
 		{
-		    close(fd);
 		    return address; //returning previously reserved memory
 		}
 		//printf(" VirtualAlloc(...) does not commit or not entirely within reserved, and\n");
 	    }
 	    /*printf(" VirtualAlloc(...) (0x%08X, %u) overlaps with (0x%08X, %u, state=%d)\n",
 	           (unsigned)address, size, (unsigned)str->address, str->mapping_size, str->state);*/
-	    close(fd);
 	    return NULL;
 	}
     }
 
-    answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
-		MAP_PRIVATE, fd, 0);
+    answer=mmap_anon(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+            MAP_PRIVATE, &fd, 0);
 //    answer=FILE_dommap(-1, address, 0, size, 0, 0,
 //	PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
-    close(fd);
+    if (fd != -1)
+        close(fd);
+
     if (answer != (void *)-1 && address && answer != address) {
 	/* It is dangerous to try mmap() with MAP_FIXED since it does not
 	   always detect conflicts or non-allocation and chaos ensues after
--- a/loader/ldt_keeper.c	Sat Nov 25 00:50:43 2006 +0000
+++ b/loader/ldt_keeper.c	Sat Nov 25 01:22:20 2006 +0000
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <stdio.h>
 #include <unistd.h>
+#include "osdep/mmap_anon.h"
 #ifdef __linux__
 #include <asm/unistd.h>
 #include <asm/ldt.h>
@@ -200,8 +201,8 @@
 	return NULL;
     }
     fs_seg=
-    ldt_fs->fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE,
-			  ldt_fs->fd, 0);
+    ldt_fs->fs_seg = mmap_anon(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, &ldt_fs->fd, 
+                0);
     if (ldt_fs->fs_seg == (void*)-1)
     {
 	perror("ERROR: Couldn't allocate memory for fs segment");
@@ -286,6 +287,7 @@
 	free(ldt_fs->prev_struct);
     munmap((char*)ldt_fs->fs_seg, getpagesize());
     ldt_fs->fs_seg = 0;
+    if (ldt_fs->fd != -1)
     close(ldt_fs->fd);
     free(ldt_fs);
 }
--- a/osdep/Makefile	Sat Nov 25 00:50:43 2006 +0000
+++ b/osdep/Makefile	Sat Nov 25 01:22:20 2006 +0000
@@ -12,6 +12,7 @@
       fseeko.c \
       swab.c \
       setenv.c \
+      mmap_anon.c \
       # timer.c \
 
 getch = getch2.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osdep/mmap_anon.c	Sat Nov 25 01:22:20 2006 +0000
@@ -0,0 +1,67 @@
+ /**
+ * \file mmap_anon.c
+ * \brief Provide a compatible anonymous space mapping function
+ */
+
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/*
+ * mmap() anonymous space, depending on the system's mmap() style. On systems
+ * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor
+ * of the opened /dev/zero. 
+ */
+ 
+ /**
+ * \brief mmap() anonymous space, depending on the system's mmap() style. On systems
+ * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor
+ * of the opened /dev/zero.
+ *
+ * \param addr address to map at.
+ * \param len number of bytes from addr to be mapped.
+ * \param prot protections (region accessibility).
+ * \param flags specifies the type of the mapped object.
+ * \param offset start mapping at byte offset.
+ * \param zerofd 
+ * \return a pointer to the mapped region upon successful completion, -1 otherwise.
+ */
+void *mmap_anon(void *addr, size_t len, int prot, int flags, int *zerofd, off_t offset)
+{
+    int fd;
+    void *result;
+
+     /* From loader/ext.c:
+      * "Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap"
+      * Therefore we preserve the same behavior on all platforms, ie. no
+      * shared mappings of anon space (if the concepts are supported). */
+#if defined(MAP_SHARED) && defined(MAP_PRIVATE)
+     flags = (flags & ~MAP_SHARED) | MAP_PRIVATE;
+#endif /* defined(MAP_SHARED) && defined(MAP_PRIVATE) */
+
+#ifdef MAP_ANONYMOUS
+    /* BSD-style anonymous mapping */
+    fd = -1;
+    result = mmap(addr, len, prot, flags | MAP_ANONYMOUS, -1, offset);
+#else
+    /* SysV-style anonymous mapping */
+    fd = open("/dev/zero", O_RDWR);
+    if(fd < 0){
+        perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: ");
+        return NULL;
+    }
+
+    result = mmap(addr, len, prot, flags, fd, offset);
+#endif /* MAP_ANONYMOUS */
+
+    if (zerofd)
+        *zerofd = fd;
+
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osdep/mmap_anon.h	Sat Nov 25 01:22:20 2006 +0000
@@ -0,0 +1,8 @@
+#ifndef _OSDEP_MMAP_ANON_H_
+#define _OSDEP_MMAP_ANON_H_
+
+#include <sys/types.h>
+
+void *mmap_anon(void *, size_t, int, int, int *, off_t);
+
+#endif /* _OSDEP_MMAP_ANON_H_ */