Subject: Call for Testers: mmap autoconf logic
From: "Zack Weinberg" <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Date: Mon, 8 Jan 2001 23:15:18 -0800

I would appreciate it if y'all would run the appended shell script and
send me its output + any nonempty .l files it generates.  (They'll be
in a subdirectory named "mmt12345" for some value of 12345.)

I do not need to know about common, modern systems (*BSD, Linux,
Solaris, IRIX >=6.2, etc.)  nor about systems known to have no mmap(2)
at all.  I am specifically interested in the behavior under cygwin;
the "works/is buggy" check is supposed to catch several bugs known to
exist in that mmap implementation.

Thanks.

zw

-- cut here --
#! /bin/sh

mkdir mmt$$ || exit 1
cd mmt$$ || exit 1

cat >testcore.h <<EOF
/* Test by Richard Henderson and Alexandre Oliva.
   Check whether mmap MAP_ANONYMOUS or mmap from /dev/zero works. */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

#ifndef MAP_ANON
# ifdef MAP_ANONYMOUS
#  define MAP_ANON MAP_ANONYMOUS
# else
#  define MAP_ANON 0
# endif
#endif

#ifndef MAP_FAILED
# define MAP_FAILED -1
#endif

static char *
anonmap (size)
     size_t size;
{
#ifdef USE_MAP_ANON
  return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|MAP_ANON, -1, 0);
#else
  static int devzero = -1;
  if (devzero == -1)
    {
      devzero = open ("/dev/zero", O_RDWR);
      if (devzero < 0)
	exit (1);
    }
  return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
			MAP_PRIVATE, devzero, 0);
#endif
}
EOF

cat >test1.c <<EOF
#include "testcore.h"

int
main()
{
  int pg = getpagesize ();
  char *x = anonmap (pg);

  if (x == (char *) MAP_FAILED)
    exit(2);

  *(int *)x += 1;

  if (munmap(x, pg) < 0)
    exit(3);

  exit(0);
}
EOF

if ${CC-cc} test1.c -o test1z.x >test1z.l 2>&1 && ./test1z.x >>test1z.l 2>&1
then echo "Have mmap from /dev/zero."
     have_dev_zero=y
else echo "No mmap from /dev/zero."
fi

if ${CC-cc} test1.c -DUSE_MAP_ANON -o test1a.x >test1a.l 2>&1 \
    && ./test1a.x >>test1a.l 2>&1
then echo "Have mmap with MAP_ANON(YMOUS)."
     have_map_anon=y
else echo "No mmap with MAP_ANON(YMOUS)."
fi

cat >test2.c <<EOF
#include "testcore.h"
#include <signal.h>
#include <setjmp.h>

/* 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 jmp_buf r;
static size_t pg;

static void
sigsegv (unused)
     int unused;
{
  longjmp (r, 1);
}

/* 1. If we map a 2-page region and unmap its second page, the first page
   must remain.  */
void
test_1 ()
{
  char *x = anonmap (pg * 2);
  if (x == (char *)MAP_FAILED)
    exit (1);

  signal (SIGSEGV, sigsegv);
  if (setjmp (r))
    exit (2);

  x[0] = 1;
  x[pg] = 1;

  munmap (x + pg, pg);
  x[0] = 2;

  if (setjmp (r))
    {
      munmap (x, pg);
      return;
    }
  x[pg] = 1;
  exit (3);
}

/* 2. If we map a 2-page region and unmap its first page, the second
   page must remain.  */
void
test_2 ()
{
  char *x = anonmap (pg * 2);
  if (x == (char *)MAP_FAILED)
    exit (4);

  signal (SIGSEGV, sigsegv);
  if (setjmp (r))
    exit (5);

  x[0] = 1;
  x[pg] = 1;

  munmap (x, pg);
  x[pg] = 2;

  if (setjmp (r))
    {
      munmap (x + pg, pg);
      return;
    }
  x[0] = 1;
  exit (6);
}

/* 3. If we map two consecutive 1-page regions and unmap them both with
   one munmap, both must go away.  */

void
test_3 ()
{
  char *x = anonmap (pg);
  char *y = anonmap (pg);
  if (x == (char *)MAP_FAILED || y == (char *)MAP_FAILED || x + pg != y)
    exit (7);

  signal (SIGSEGV, sigsegv);
  if (setjmp (r))
    exit (8);

  x[0] = 1;
  x[pg] = 1;

  munmap (x, pg * 2);

  if (setjmp (r) == 0)
    {
      x[0] = 1;
      exit (9);
    }
  
  signal (SIGSEGV, sigsegv);
  if (setjmp (r) == 0)
    {
      x[pg] = 1;
      exit (10);
    }
}

int
main ()
{
  pg = getpagesize ();

  test_1();
  test_2();
  test_3();

  exit(0);
}
EOF

if test -n "$have_dev_zero"; then
  if ${CC-cc} test2.c  -o test2z.x >test2z.l 2>&1 \
     && ./test2z.x >>test2z.l 2>&1
  then echo "mmap of /dev/zero works."
  else echo "mmap of /dev/zero is buggy. ($?)"
  fi
fi

if test -n "$have_map_anon"; then 
  if ${CC-cc} test2.c -DUSE_MAP_ANON -o test2a.x >test2a.l 2>&1 \
     && ./test2a.x >>test2a.l 2>&1
  then echo "mmap with MAP_ANON(YMOUS) works."
  else echo "mmap with MAP_ANON(YMOUS) is buggy. ($?)"
  fi
fi

ls -l *.l

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple