mmap checks by blacklist, not fragile AC_TRY_RUN test
Zack Weinberg
zack@codesourcery.com
Mon Jun 2 04:45:00 GMT 2003
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.
zw
> 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
More information about the Gcc-patches
mailing list