This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: mmap checks by blacklist, not fragile AC_TRY_RUN test


On Sun, Jun 01, 2003 at 09:45:03PM -0700, Zack Weinberg wrote:
>Zack Weinberg <zack@codesourcery.com> writes:
>
>> i686-linux bootstrap running; testing would be appreciated on
>> blacklisted systems, and/or under the conditions that prompted the
>> original bug reports.
>
>The original patch had a pair of typos which made it think /dev/zero
>and MAP_ANON never worked.  That caused an entertaining failure of
>PCH; I suspect the fallback-to-fread logic has never been tested.
>This patch has been corrected.
>
>I am going to check in the change to ggc-page.c, which is independent,
>but wait another 24 hours for more feedback on the configure changes.
>This diff includes only the configure changes.

I'm not sure that blacklisting cygwin re /dev/zero is correct.  It might
have been correct at one point but recent versions may work correctly.
Did you determine this from direct testing?

cgf


>>         PR bootstrap/3163
>>         * aclocal.m4 (AC_FUNC_MMAP_ANYWHERE, AC_FUNC_MMAP_FILE): Delete.
>>         (gcc_AC_FUNC_MMAP_BLACKLIST): New.
>>         * configure.in: Check for sys/mman.h and mmap in AC_CHECK_HEADERS
>>         and AC_CHECK_FUNCS lists, respectively.  Use
>>         gcc_AC_FUNC_MMAP_BLACKLIST, not AC_FUNC_MMAP_ANYWHERE nor
>>         AC_FUNC_MMAP_FILE.
>>         * configure, config.in: Regenerate.
>
>===================================================================
>Index: aclocal.m4
>--- aclocal.m4	21 Mar 2003 17:19:32 -0000	1.67
>+++ aclocal.m4	2 Jun 2003 04:42:46 -0000
>@@ -398,356 +398,92 @@ fi
> AC_SUBST($1)dnl
> ])
> 
>-# Check whether mmap can map an arbitrary page from /dev/zero or with
>-# MAP_ANONYMOUS, without MAP_FIXED.
>-AC_DEFUN([AC_FUNC_MMAP_ANYWHERE],
>-[AC_CHECK_FUNCS(getpagesize)
>-# The test program for the next two tests is the same except for one
>-# set of ifdefs.
>-changequote({{{,}}})dnl
>-{{{cat >ct-mmap.inc <<'EOF'
>-#include <sys/types.h>
>+# mmap(2) blacklisting.  Some platforms provide the mmap library routine
>+# but don't support all of the features we need from it.
>+AC_DEFUN([gcc_AC_FUNC_MMAP_BLACKLIST],
>+[if test $ac_cv_header_sys_mman_h != yes \
>+ || test $ac_cv_func_mmap != yes; then
>+   gcc_cv_func_mmap_file=no
>+   gcc_cv_func_mmap_dev_zero=no
>+   gcc_cv_func_mmap_anon=no
>+else
>+   AC_CACHE_CHECK([whether read-only mmap of a plain file works], 
>+  gcc_cv_func_mmap_file,
>+  [# Add a system to this blacklist if 
>+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
>+   # memory area containing the same data that you'd get if you applied
>+   # read() to the same fd.  The only system known to have a problem here
>+   # is VMS, where text files have record structure.
>+   case "$host_os" in
>+     vms*) 
>+        gcc_cv_func_mmap_file=no ;;
>+     *)
>+        gcc_cv_func_mmap_file=yes;;
>+   esac])
>+   AC_CACHE_CHECK([whether mmap from /dev/zero works],
>+  gcc_cv_func_mmap_dev_zero,
>+  [# Add a system to this blacklist if it has mmap() but /dev/zero
>+   # does not exist, or if mmapping /dev/zero does not give anonymous
>+   # zeroed pages with both the following properties:
>+   # 1. If you map N consecutive pages in with one call, and then
>+   #    unmap any subset of those pages, the pages that were not
>+   #    explicitly unmapped remain accessible.
>+   # 2. If you map two adjacent blocks of memory and then unmap them
>+   #    both at once, they must both go away.
>+   # Systems known to be in this category are Windows (all variants),
>+   # VMS, and Darwin.
>+   case "$host_os" in
>+     vms* | cygwin* | pe | mingw* | darwin*)
>+        gcc_cv_func_mmap_dev_zero=no ;;
>+     *)
>+        gcc_cv_func_mmap_dev_zero=yes;;
>+   esac])
>+
>+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
>+   AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon,
>+    [AC_TRY_COMPILE(
>+[#include <sys/types.h>
> #include <sys/mman.h>
>-#include <fcntl.h>
>-#include <signal.h>
>-#include <setjmp.h>
>-#include <stdio.h>
>+#include <unistd.h>
> 
>-#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
>-# define MAP_ANONYMOUS MAP_ANON
>+#ifndef MAP_ANONYMOUS
>+#define MAP_ANONYMOUS MAP_ANON
> #endif
>-
>-/* This mess was copied from the GNU getpagesize.h.  */
>-#ifndef HAVE_GETPAGESIZE
>-# ifdef HAVE_UNISTD_H
>-#  include <unistd.h>
>-# endif
>-
>-/* Assume that all systems that can run configure have sys/param.h.  */
>-# ifndef HAVE_SYS_PARAM_H
>-#  define HAVE_SYS_PARAM_H 1
>-# endif
>-
>-# ifdef _SC_PAGESIZE
>-#  define getpagesize() sysconf(_SC_PAGESIZE)
>-# else /* no _SC_PAGESIZE */
>-#  ifdef HAVE_SYS_PARAM_H
>-#   include <sys/param.h>
>-#   ifdef EXEC_PAGESIZE
>-#    define getpagesize() EXEC_PAGESIZE
>-#   else /* no EXEC_PAGESIZE */
>-#    ifdef NBPG
>-#     define getpagesize() NBPG * CLSIZE
>-#     ifndef CLSIZE
>-#      define CLSIZE 1
>-#     endif /* no CLSIZE */
>-#    else /* no NBPG */
>-#     ifdef NBPC
>-#      define getpagesize() NBPC
>-#     else /* no NBPC */
>-#      ifdef PAGESIZE
>-#       define getpagesize() PAGESIZE
>-#      endif /* PAGESIZE */
>-#     endif /* no NBPC */
>-#    endif /* no NBPG */
>-#   endif /* no EXEC_PAGESIZE */
>-#  else /* no HAVE_SYS_PARAM_H */
>-#   define getpagesize() 8192	/* punt totally */
>-#  endif /* no HAVE_SYS_PARAM_H */
>-# endif /* no _SC_PAGESIZE */
>-
>-#endif /* no HAVE_GETPAGESIZE */
>-
>-#ifndef MAP_FAILED
>-# define MAP_FAILED -1
>-#endif
>-
>-#undef perror_exit
>-#define perror_exit(str, val) \
>-  do { perror(str); exit(val); } while (0)
>-
>-/* Some versions of cygwin mmap require that munmap is called with the
>-   same parameters as mmap.  GCC expects that this is not the case.
>-   Test for various forms of this problem.  Warning - icky signal games.  */
>-
>-static sigset_t unblock_sigsegv;
>-static jmp_buf r;
>-static size_t pg;
>-static int devzero;
>-
>-static char *
>-anonmap (size)
>-     size_t size;
>-{
>-#ifdef USE_MAP_ANON
>-  return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
>-			MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
>-#else
>-  return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
>-			MAP_PRIVATE, devzero, 0);
>-#endif
>-}
>-
>-static void
>-sigsegv (unused)
>-     int unused;
>-{
>-  sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0);
>-  longjmp (r, 1);
>-}
>-
>-/* Basic functionality test.  */
>-void
>-test_0 ()
>-{
>-  char *x = anonmap (pg);
>-  if (x == (char *) MAP_FAILED)
>-    perror_exit("test 0 mmap", 2);
>-
>-  *(int *)x += 1;
>-
>-  if (munmap(x, pg) < 0)
>-    perror_exit("test 0 munmap", 3);
>-}
>-
>-/* 1. If we map a 2-page region and unmap its second page, the first page
>-   must remain.  */
>-static void
>-test_1 ()
>-{
>-  char *x = anonmap (pg * 2);
>-  if (x == (char *)MAP_FAILED)
>-    perror_exit ("test 1 mmap", 4);
>-
>-  signal (SIGSEGV, sigsegv);
>-  if (setjmp (r))
>-    perror_exit ("test 1 fault", 5);
>-
>-  x[0] = 1;
>-  x[pg] = 1;
>-
>-  if (munmap (x + pg, pg) < 0)
>-    perror_exit ("test 1 munmap 1", 6);
>-  x[0] = 2;
>-
>-  if (setjmp (r) == 0)
>-    {
>-      x[pg] = 1;
>-      perror_exit ("test 1 no fault", 7);
>-    }
>-  if (munmap (x, pg) < 0)
>-    perror_exit ("test 1 munmap 2", 8);
>-}
>-
>-/* 2. If we map a 2-page region and unmap its first page, the second
>-   page must remain.  */
>-static void
>-test_2 ()
>-{
>-  char *x = anonmap (pg * 2);
>-  if (x == (char *)MAP_FAILED)
>-    perror_exit ("test 2 mmap", 9);
>-
>-  signal (SIGSEGV, sigsegv);
>-  if (setjmp (r))
>-    perror_exit ("test 2 fault", 10);
>-
>-  x[0] = 1;
>-  x[pg] = 1;
>-
>-  if (munmap (x, pg) < 0)
>-    perror_exit ("test 2 munmap 1", 11);
>-
>-  x[pg] = 2;
>-
>-  if (setjmp (r) == 0)
>-    {
>-      x[0] = 1;
>-      perror_exit ("test 2 no fault", 12);
>-    }
>-
>-  if (munmap (x+pg, pg) < 0)
>-    perror_exit ("test 2 munmap 2", 13);
>-}
>-
>-/* 3. If we map two adjacent 1-page regions and unmap them both with
>-   one munmap, both must go away.
>-
>-   Getting two adjacent 1-page regions with two mmap calls is slightly
>-   tricky.  All OS's tested skip over already-allocated blocks; therefore
>-   we have been careful to unmap all allocated regions in previous tests.
>-   HP/UX allocates pages backward in memory.  No OS has yet been observed
>-   to be so perverse as to leave unmapped space between consecutive calls
>-   to mmap.  */
>-
>-static void
>-test_3 ()
>-{
>-  char *x, *y, *z;
>-
>-  x = anonmap (pg);
>-  if (x == (char *)MAP_FAILED)
>-    perror_exit ("test 3 mmap 1", 14);
>-  y = anonmap (pg);
>-  if (y == (char *)MAP_FAILED)
>-    perror_exit ("test 3 mmap 2", 15);
>-
>-  if (y != x + pg)
>-    {
>-      if (y == x - pg)
>-	z = y, y = x, x = z;
>-      else
>-	{
>-	  fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n",
>-		   (unsigned long)x, (unsigned long)y);
>-	  exit (16);
>-	}
>-    }
>-
>-  signal (SIGSEGV, sigsegv);
>-  if (setjmp (r))
>-    perror_exit ("test 3 fault", 17);
>-
>-  x[0] = 1;
>-  y[0] = 1;
>-
>-  if (munmap (x, pg*2) < 0)
>-    perror_exit ("test 3 munmap", 18);
>-
>-  if (setjmp (r) == 0)
>-    {
>-      x[0] = 1;
>-      perror_exit ("test 3 no fault 1", 19);
>-    }
>-  
>-  signal (SIGSEGV, sigsegv);
>-  if (setjmp (r) == 0)
>-    {
>-      y[0] = 1;
>-      perror_exit ("test 3 no fault 2", 20);
>-    }
>-}
>-
>-int
>-main ()
>-{
>-  sigemptyset (&unblock_sigsegv);
>-  sigaddset (&unblock_sigsegv, SIGSEGV);
>-  pg = getpagesize ();
>-#ifndef USE_MAP_ANON
>-  devzero = open ("/dev/zero", O_RDWR);
>-  if (devzero < 0)
>-    perror_exit ("open /dev/zero", 1);
>-#endif
>-
>-  test_0();
>-  test_1();
>-  test_2();
>-  test_3();
>-
>-  exit(0);
>-}
>-EOF}}}
>-changequote([,])dnl
>-
>-AC_CACHE_CHECK(for working mmap from /dev/zero,
>-  ac_cv_func_mmap_dev_zero,
>-[AC_TRY_RUN(
>- [#include "ct-mmap.inc"],
>- ac_cv_func_mmap_dev_zero=yes,
>- [if test $? -lt 4
>- then ac_cv_func_mmap_dev_zero=no
>- else ac_cv_func_mmap_dev_zero=buggy
>- fi],
>- # When cross-building, assume that this works, unless we know it
>- # doesn't.  Of course, we have no way of knowing if there even is a /dev/zero
>- # on the host, let alone whether mmap will work on it.
>- [case "$host_os" in
>-   cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;;
>-   darwin* ) ac_cv_func_mmap_dev_zero=no ;;
>-   * ) ac_cv_func_mmap_dev_zero=yes ;;
>-  esac])
>-])
>-if test $ac_cv_func_mmap_dev_zero = yes; then
>-  AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
>-	    [Define if mmap can get us zeroed pages from /dev/zero.])
>+],
>+[int n = MAP_ANONYMOUS;],
>+    gcc_cv_decl_map_anon=yes,
>+    gcc_cv_decl_map_anon=no)])
>+
>+   if test $gcc_cv_decl_map_anon = no; then
>+     gcc_cv_func_mmap_anon=no
>+   else
>+     AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
>+     gcc_cv_func_mmap_anon,
>+  [# Add a system to this blacklist if it has mmap() and MAP_ANON or
>+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
>+   # doesn't give anonymous zeroed pages with the same properties listed
>+   # above for use of /dev/zero.
>+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
>+   case "$host_os" in
>+     vms* | cygwin* | pe | mingw* | sco* | udk* )
>+        gcc_cv_func_mmap_anon=no ;;
>+     *)
>+        gcc_cv_func_mmap_anon=yes;;
>+   esac])
>+   fi
> fi
> 
>-AC_CACHE_CHECK([for working mmap with MAP_ANON(YMOUS)],
>-  ac_cv_func_mmap_anon,
>-[AC_TRY_RUN(
>- [#define USE_MAP_ANON
>-#include "ct-mmap.inc"],
>- ac_cv_func_mmap_anon=yes,
>- [if test $? -lt 4
>- then ac_cv_func_mmap_anon=no
>- else ac_cv_func_mmap_anon=buggy
>- fi],
>- # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works
>- # just because it's there. Some SCO Un*xen define it but don't implement it.
>- [case "$host_os" in
>-   darwin* ) ac_cv_func_mmap_anon=yes ;;
>-   * ) ac_cv_func_mmap_anon=no ;;
>-  esac])
>-])
>-if test $ac_cv_func_mmap_anon = yes; then
>-  AC_DEFINE(HAVE_MMAP_ANON, 1,
>-	    [Define if mmap can get us zeroed pages using MAP_ANON(YMOUS).])
>-fi
>-rm -f ct-mmap.inc
>-])
>-
>-# Check whether mmap can map a plain file, without MAP_FIXED.
>-AC_DEFUN([AC_FUNC_MMAP_FILE], 
>-[AC_CACHE_CHECK(for working mmap of a file, ac_cv_func_mmap_file,
>-[# Create a file one thousand bytes long.
>-for i in 1 2 3 4 5 6 7 8 9 0
>-do for j in 1 2 3 4 5 6 7 8 9 0
>-do echo $i $j xxxxx
>-done
>-done > conftestdata$$
>-
>-AC_TRY_RUN([
>-/* Test by Zack Weinberg.  Modified from MMAP_ANYWHERE test by
>-   Richard Henderson and Alexandre Oliva.
>-   Check whether read-only mmap of a plain file works. */
>-#include <sys/types.h>
>-#include <sys/stat.h>
>-#include <fcntl.h>
>-#include <sys/mman.h>
>-
>-int main()
>-{
>-  char *x;
>-  int fd;
>-  struct stat st;
>-
>-  fd = open("conftestdata$$", O_RDONLY);
>-  if (fd < 0)
>-    exit(1);
>-
>-  if (fstat (fd, &st))
>-    exit(2);
>-
>-  x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
>-  if (x == (char *) -1)
>-    exit(3);
>-
>-  if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ')
>-    exit(4);
>-
>-  if (munmap(x, st.st_size) < 0)
>-    exit(5);
>-
>-  exit(0);
>-}], ac_cv_func_mmap_file=yes, ac_cv_func_mmap_file=no,
>- [case "$host_os" in
>-   darwin* ) ac_cv_func_mmap_file=yes ;;
>-   * ) ac_cv_func_mmap_file=no ;;
>-  esac])])
>-if test $ac_cv_func_mmap_file = yes; then
>+if test $gcc_cv_func_mmap_file = yes; then
>   AC_DEFINE(HAVE_MMAP_FILE, 1,
> 	    [Define if read-only mmap of a plain file works.])
>+fi
>+if test $gcc_cv_func_mmap_dev_zero = yes; then
>+  AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
>+	    [Define if mmap of /dev/zero works.])
>+fi
>+if test $gcc_cv_func_mmap_anon = yes; then
>+  AC_DEFINE(HAVE_MMAP_ANON, 1,
>+	    [Define if mmap with MAP_ANON(YMOUS) works.])
> fi
> ])
> 
>===================================================================
>Index: configure.in
>--- configure.in	12 May 2003 22:30:24 -0000	1.668
>+++ configure.in	2 Jun 2003 04:42:47 -0000
>@@ -706,7 +706,7 @@ gcc_AC_HEADER_STDBOOL
> gcc_AC_HEADER_STRING
> AC_HEADER_SYS_WAIT
> AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h \
>-		 fcntl.h unistd.h sys/file.h sys/time.h \
>+		 fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \
> 		 sys/resource.h sys/param.h sys/times.h sys/stat.h \
> 		 direct.h malloc.h langinfo.h ldfcn.h wchar.h)
> 
>@@ -807,7 +807,7 @@ dnl gcc_AC_C_ENUM_BF_UNSIGNED
> AC_CHECK_FUNCS(times clock dup2 kill getrlimit setrlimit atoll atoq \
> 	sysconf strsignal putc_unlocked fputc_unlocked fputs_unlocked \
> 	fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat \
>-        scandir alphasort gettimeofday mbstowcs wcswidth)
>+        scandir alphasort gettimeofday mbstowcs wcswidth mmap)
> 
> if test x$ac_cv_func_mbstowcs = xyes; then
>   AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
>@@ -850,6 +850,7 @@ fi
> AC_SUBST(TARGET_GETGROUPS_T)
> 
> gcc_AC_FUNC_PRINTF_PTR
>+gcc_AC_FUNC_MMAP_BLACKLIST
> 
> case "${host}" in
> *-*-uwin*)
>@@ -865,8 +866,6 @@ case "${host}" in
>   ;;
> esac
> AC_FUNC_VFORK
>-AC_FUNC_MMAP_ANYWHERE
>-AC_FUNC_MMAP_FILE
> 
> AM_ICONV
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]