Commit 825b6926 by Zack Weinberg

aclocal.m4 (AC_FUNC_MMAP_ANYWHERE): Completely rewritten.

2001-01-11  Zack Weinberg  <zack@wolery.stanford.edu>

	* aclocal.m4 (AC_FUNC_MMAP_ANYWHERE): Completely rewritten.
	Now defines HAVE_MMAP_DEV_ZERO and/or HAVE_MMAP_ANON depending
	which you have.
	(AC_FUNC_MMAP_FILE): Don't AC_REQUIRE AC_FUNC_MMAP_ANYWHERE.
	* configure.in: Set GGC to ggc-page if any of mmap_dev_zero,
	mmap_anon, and valloc is available.
	* ggc-page.c: Restructure ifdef logic to match new autoconf
	spec.  Don't throw away the test page in init_ggc.

	* configure, config.in: Regenerate.

From-SVN: r38934
parent 099f0f3f
......@@ -737,16 +737,17 @@ 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_HEADERS(unistd.h)
AC_CHECK_FUNCS(getpagesize)
AC_CACHE_CHECK(for working mmap which provides zeroed pages anywhere,
ac_cv_func_mmap_anywhere,
[AC_TRY_RUN([
/* Test by Richard Henderson and Alexandre Oliva.
Check whether mmap MAP_ANONYMOUS or mmap from /dev/zero works. */
[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>
#include <fcntl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
# define MAP_ANONYMOUS MAP_ANON
......@@ -793,45 +794,246 @@ AC_CACHE_CHECK(for working mmap which provides zeroed pages anywhere,
#endif /* no HAVE_GETPAGESIZE */
int main()
{
char *x;
int fd, pg;
#ifndef MAP_ANONYMOUS
fd = open("/dev/zero", O_RDWR);
if (fd < 0)
exit(1);
#ifndef MAP_FAILED
# define MAP_FAILED -1
#endif
pg = getpagesize();
#ifdef MAP_ANONYMOUS
x = (char*)mmap(0, pg, PROT_READ|PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#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
x = (char*)mmap(0, pg, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE, devzero, 0);
#endif
if (x == (char *) -1)
exit(2);
}
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)
exit(3);
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);
}], ac_cv_func_mmap_anywhere=yes, ac_cv_func_mmap_anywhere=no,
ac_cv_func_mmap_anywhere=no)])
if test $ac_cv_func_mmap_anywhere = yes; then
AC_DEFINE(HAVE_MMAP_ANYWHERE, 1,
[Define if mmap can get us zeroed pages without MAP_FIXED.])
}
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],
# If this is not cygwin, and /dev/zero is a character device, it's probably
# safe to assume it works.
[case "$host_os" in
cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;;
* ) if test -c /dev/zero
then ac_cv_func_mmap_dev_zero=yes
else ac_cv_func_mmap_dev_zero=no
fi ;;
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.])
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.
ac_cv_func_mmap_anon=no)
])
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_REQUIRE([AC_FUNC_MMAP_ANYWHERE])dnl
AC_CACHE_CHECK(for working mmap of a file, ac_cv_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
......
......@@ -330,8 +330,11 @@
/* Define if printf supports %p. */
#undef HAVE_PRINTF_PTR
/* Define if mmap can get us zeroed pages without MAP_FIXED. */
#undef HAVE_MMAP_ANYWHERE
/* Define if mmap can get us zeroed pages from /dev/zero. */
#undef HAVE_MMAP_DEV_ZERO
/* Define if mmap can get us zeroed pages using MAP_ANON(YMOUS). */
#undef HAVE_MMAP_ANON
/* Define if read-only mmap of a plain file works. */
#undef HAVE_MMAP_FILE
......
......@@ -1565,7 +1565,8 @@ AC_ARG_WITH(gc,
AC_MSG_ERROR([$withval is an invalid option to --with-gc])
;;
esac],
[if test $ac_cv_func_mmap_anywhere = yes \
[if test $ac_cv_func_mmap_dev_zero = yes \
|| test $ac_cv_func_mmap_anon = yes \
|| test $ac_cv_func_valloc = yes; then
GGC=ggc-page
else
......
......@@ -29,16 +29,37 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h"
#include "timevar.h"
#ifdef HAVE_MMAP_ANYWHERE
#include <sys/mman.h>
/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
file open. Prefer either to valloc. */
#ifdef HAVE_MMAP_ANON
# undef HAVE_MMAP_DEV_ZERO
# undef HAVE_VALLOC
# include <sys/mman.h>
# ifndef MAP_FAILED
# define MAP_FAILED -1
# endif
# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
# define MAP_ANONYMOUS MAP_ANON
# endif
# define USING_MMAP
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#ifdef HAVE_MMAP_DEV_ZERO
# undef HAVE_VALLOC
# include <sys/mman.h>
# ifndef MAP_FAILED
# define MAP_FAILED -1
# endif
# define USING_MMAP
#endif
#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#ifdef HAVE_VALLOC
# undef MAP_FAILED
# define MAP_FAILED 0
#endif
/* Stategy:
......@@ -279,7 +300,7 @@ static struct globals
unsigned short context_depth;
/* A file descriptor open to /dev/zero for reading. */
#if defined (HAVE_MMAP_ANYWHERE) && !defined(MAP_ANONYMOUS)
#if defined (HAVE_MMAP_DEV_ZERO)
int dev_zero_fd;
#endif
......@@ -445,38 +466,31 @@ debug_print_page_list (order)
}
/* Allocate SIZE bytes of anonymous memory, preferably near PREF,
(if non-null). */
(if non-null). The ifdef structure here is intended to cause a
compile error unless exactly one of the HAVE_* is defined. */
static inline char *
alloc_anon (pref, size)
char *pref ATTRIBUTE_UNUSED;
size_t size;
{
char *page;
#ifdef HAVE_MMAP_ANYWHERE
#ifdef MAP_ANONYMOUS
page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#else
page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE, G.dev_zero_fd, 0);
#ifdef HAVE_MMAP_ANON
char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif
#ifdef HAVE_MMAP_DEV_ZERO
char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE, G.dev_zero_fd, 0);
#endif
if (page == (char *) MAP_FAILED)
{
fputs ("Virtual memory exhausted!\n", stderr);
exit(1);
}
#else
#ifdef HAVE_VALLOC
page = (char *) valloc (size);
if (!page)
char *page = (char *) valloc (size);
#endif
if (page == (char *) MAP_FAILED)
{
fputs ("Virtual memory exhausted!\n", stderr);
exit(1);
}
#endif /* HAVE_VALLOC */
#endif /* HAVE_MMAP_ANYWHERE */
/* Remember that we allocated this memory. */
G.bytes_mapped += size;
......@@ -526,7 +540,7 @@ alloc_page (order)
else
free (p);
}
#ifdef HAVE_MMAP_ANYWHERE
#ifdef USING_MMAP
else if (entry_size == G.pagesize)
{
/* We want just one page. Allocate a bunch of them and put the
......@@ -601,7 +615,7 @@ release_pages ()
{
page_entry *p, *next;
#ifdef HAVE_MMAP_ANYWHERE
#ifdef USING_MMAP
char *start;
size_t len;
......@@ -628,8 +642,6 @@ release_pages ()
G.bytes_mapped -= len;
}
#else
#ifdef HAVE_VALLOC
for (p = G.free_pages; p; p = next)
{
next = p->next;
......@@ -637,8 +649,7 @@ release_pages ()
G.bytes_mapped -= p->bytes;
free (p);
}
#endif /* HAVE_VALLOC */
#endif /* HAVE_MMAP_ANYWHERE */
#endif /* USING_MMAP */
G.free_pages = NULL;
}
......@@ -849,7 +860,7 @@ init_ggc ()
G.pagesize = getpagesize();
G.lg_pagesize = exact_log2 (G.pagesize);
#if defined (HAVE_MMAP_ANYWHERE) && !defined(MAP_ANONYMOUS)
#ifdef HAVE_MMAP_DEV_ZERO
G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
if (G.dev_zero_fd == -1)
abort ();
......@@ -863,13 +874,14 @@ init_ggc ()
G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
#ifdef HAVE_MMAP_ANYWHERE
#ifdef USING_MMAP
/* StunOS has an amazing off-by-one error for the first mmap allocation
after fiddling with RLIMIT_STACK. The result, as hard as it is to
believe, is an unaligned page allocation, which would cause us to
hork badly if we tried to use it. */
{
char *p = alloc_anon (NULL, G.pagesize);
struct page_entry *e;
if ((size_t)p & (G.pagesize - 1))
{
/* How losing. Discard this one and try another. If we still
......@@ -879,7 +891,13 @@ init_ggc ()
if ((size_t)p & (G.pagesize - 1))
abort ();
}
munmap (p, G.pagesize);
/* We have a good page, might as well hold onto it... */
e = (struct page_entry *) xcalloc (1, sizeof (struct page_entry));
e->bytes = G.pagesize;
e->page = p;
e->next = G.free_pages;
G.free_pages = e;
}
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment