Patchwork Fix gcc.dg/pch/largefile.c on Solaris < 11 (PR pch/14940)

login
register
mail settings
Submitter Rainer Orth
Date July 12, 2010, 11:57 a.m.
Message ID <yddfwzoud2y.fsf@manam.CeBiTec.Uni-Bielefeld.DE>
Download mbox | patch
Permalink /patch/58597/
State New
Headers show

Comments

Rainer Orth - July 12, 2010, 11:57 a.m.
The PCH largefile test was still failing before Solaris 11 (x86 only):

FAIL: largefile.c  -O0 -g -I. (internal compiler error)
FAIL: largefile.c  -O0 -g -I. (test for excess errors)
FAIL: gcc.dg/pch/largefile.c  -O0 -g assembly comparison
FAIL: largefile.c   -O0  -I. (internal compiler error)
FAIL: largefile.c   -O0  -I. (test for excess errors)
FAIL: gcc.dg/pch/largefile.c   -O0  assembly comparison

despite

	PATCH: Fix gcc.dg/pch/largefile.c on Solaris 2 (PR pch/14940)
	http://gcc.gnu.org/ml/gcc-patches/2010-02/msg00979.html

The reason is simple: just as in sol_gt_pch_use_address, the mmap call
in sol_gt_pch_get_address would ignore the base address passed
(TRY_EMPTY_VM_SPACE) and return a different address.  Once this was
understood, the solution is obvious: if mmap (addr, ...) doesn't
return addr, try again with MAP_FIXED set, as sol_gt_pch_use_address
already does.

The following patch implements this.  Bootstrapped without regression on
Solaris 8 to 11/x86.  Installed on mainline; will backport to the 4.4
and 4.5 branches once testing completes.

	Rainer

2010-06-19  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	PR pch/14940
	* config/host-solaris.c (mmap_fixed): New function.
	(sol_gt_pch_get_address): Use it.
	(sol_gt_pch_use_address): Likewise.

Patch

diff -r 33ce5a1753c7 gcc/config/host-solaris.c
--- a/gcc/config/host-solaris.c	Fri Jul 09 12:51:42 2010 +0200
+++ b/gcc/config/host-solaris.c	Fri Jul 09 12:54:23 2010 +0200
@@ -30,6 +30,41 @@ 
 #undef HOST_HOOKS_GT_PCH_USE_ADDRESS
 #define HOST_HOOKS_GT_PCH_USE_ADDRESS sol_gt_pch_use_address
 
+/* Before Solaris 11, the mmap ADDR parameter is mostly ignored without
+   MAP_FIXED set.  Before we give up, search the desired address space with
+   mincore to see if the space is really free.  */
+
+static void *
+mmap_fixed (void *addr, size_t len, int prot, int flags, int fd, off_t off)
+{
+  void *base;
+
+  base = mmap ((caddr_t) addr, len, prot, flags, fd, off);
+  
+  if (base != addr)
+    {
+      size_t page_size = getpagesize();
+      char one_byte;
+      size_t i;
+
+      if (base != (void *) MAP_FAILED)
+	munmap ((caddr_t) base, len);
+
+      errno = 0;
+      for (i = 0; i < len; i += page_size)
+	if (mincore ((char *)addr + i, page_size, (char *) &one_byte) == -1
+	    && errno == ENOMEM)
+	  continue; /* The page is not mapped.  */
+	else
+	  break;
+
+      if (i >= len)
+	base = mmap ((caddr_t) addr, len, prot, flags | MAP_FIXED, fd, off);
+    }
+
+  return base;
+}
+
 /* For various ports, try to guess a fixed spot in the vm space
    that's probably free.  Based on McDougall, Mauro, Solaris Internals, 2nd
    ed., p.460-461, fig. 9-3, 9-4, 9-5.  */
@@ -55,8 +90,8 @@ 
 {
   void *addr;
 
-  addr = mmap ((caddr_t) TRY_EMPTY_VM_SPACE, size, PROT_READ | PROT_WRITE,
-	       MAP_PRIVATE, fd, 0);
+  addr = mmap_fixed ((caddr_t) TRY_EMPTY_VM_SPACE, size,
+		     PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
   /* If we failed the map, that means there's *no* free space.  */
   if (addr == (void *) MAP_FAILED)
@@ -81,34 +116,8 @@ 
   if (size == 0)
     return -1;
 
-  addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
-	       fd, offset);
-
-  /* Solaris isn't good about honoring the mmap START parameter
-     without MAP_FIXED set.  Before we give up, search the desired
-     address space with mincore to see if the space is really free.  */
-  if (addr != base)
-    {
-      size_t page_size = getpagesize();
-      char one_byte;
-      size_t i;
-
-      if (addr != (void *) MAP_FAILED)
-	munmap ((caddr_t) addr, size);
-
-      errno = 0;
-      for (i = 0; i < size; i += page_size)
-	if (mincore ((char *)base + i, page_size, (char *) &one_byte) == -1
-	    && errno == ENOMEM)
-	  continue; /* The page is not mapped.  */
-	else
-	  break;
-
-      if (i >= size)
-	addr = mmap ((caddr_t) base, size, 
-		     PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
-		     fd, offset);
-    }
+  addr = mmap_fixed ((caddr_t) base, size,
+		     PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset);
 
   return addr == base ? 1 : -1;
 }