Solaris X86 mmap...

Robert Lunnon bob at yarrabee.net.au
Fri Aug 31 06:16:18 CDT 2001


The attached patch works for Solaris to fix the mmap problem. I have
submitted it to wine-patches on behalf of whoever authored it in the first
place


Alexandre Julliard wrote:

> Robert Lunnon <bob at yarrabee.net.au> writes:
>
> > After that point I can't find any reference to this patch, it certainly
> > hasn't made it into the CVS yet ?
> >
> > Does anyone know the outcome of this work, or am I the only Solaris X86
> > user out there :-)
>
> Last I heard it needed someone to test it on Solaris x86, but nobody
> ever did. So yes it seems you may be the only user out there... If you
> tested it and it works for you, please submit it to wine-patches.
>
> --
> Alexandre Julliard
> julliard at winehq.com
-------------- next part --------------
--- wine-cvs/library/port.c     Mon Dec 25 14:40:54 2000
+++ wine-uw/library/port.c      Thu Jan 11 02:34:28 2001
@@ -399,6 +399,87 @@
 }
 #endif /* HAVE_GETRLIMIT */

+
+#ifdef __svr4__
+/***********************************************************************
+ *             solaris_try_mmap
+ *
+ * The purpose of this routine is to emulate the behaviour of
+ * the Linux mmap() routine if a non-NULL address is passed,
+ * but the MAP_FIXED flag is not set.  Linux in this case tries
+ * to place the mapping at the specified address, *unless* the
+ * range is already in use.  Solaris, however, completely ignores
+ * the address argument in this case.
+ *
+ * As Wine code occasionally relies on the Linux behaviour, e.g. to
+ * be able to map non-relocateable PE executables to their proper
+ * start addresses, or to map the DOS memory to 0, this routine
+ * emulates the Linux behaviour by checking whether the desired
+ * address range is still available, and placing the mapping there
+ * using MAP_FIXED if so.
+ */
+static int solaris_try_mmap (void *addr, size_t len, int prot, int flags,
+                            int fildes, off_t off)
+{
+    char * volatile result = NULL;
+    int pagesize = getpagesize();
+    pid_t pid;
+
+    /* We only try to map to a fixed address if
+       addr is non-NULL and properly aligned,
+       and MAP_FIXED isn't already specified. */
+
+    if ( !addr )
+        return FALSE;
+    if ( (uintptr_t)addr & (pagesize-1) )
+        return FALSE;
+    if ( flags & MAP_FIXED )
+        return FALSE;
+
+    /* We use vfork() to freeze all threads of the
+       current process.  This allows us to check without
+       race condition whether the desired memory range is
+       already in use.  Note that because vfork() shares
+       the address spaces between parent and child, we
+       can actually perform the mapping in the child. */
+
+    if ( (pid = vfork()) == -1 )
+    {
+        perror("solaris_try_mmap: vfork");
+        exit(1);
+    }
+    if ( pid == 0 )
+    {
+        int i;
+        char vec;
+
+        /* We call mincore() for every page in the desired range.
+           If any of these calls succeeds, the page is already
+           mapped and we must fail. */
+        for ( i = 0; i < len; i += pagesize )
+            if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
+               _exit(1);
+
+        /* Perform the mapping with MAP_FIXED set.  This is safe
+           now, as none of the pages is currently in use. */
+        result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
+        if ( result == addr )
+            _exit(0);
+
+        if ( result != (void *) -1 ) /* This should never happen ... */
+            munmap( result, len );
+
+       _exit(1);
+    }
+
+    /* vfork() lets the parent continue only after the child
+       has exited.  Furthermore, Wine sets SIGCHLD to SIG_IGN,
+       so we don't need to wait for the child. */
+
+    return result == addr;
+}
+#endif
+
 /***********************************************************************
  *             wine_anon_mmap
  *
@@ -428,6 +509,11 @@
     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
 #ifdef MAP_PRIVATE
     flags |= MAP_PRIVATE;
+#endif
+
+#ifdef __svr4__
+    if ( solaris_try_mmap( start, size, prot, flags, fdzero, 0 ) )
+        return start;
 #endif

     return mmap( start, size, prot, flags, fdzero, 0 );

--


More information about the wine-patches mailing list