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