This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


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

mmap() and MAP_FIXED



I started to build the apache2.0a3 public alpha and configure
fails when checking for a working mmap().  The test (with my
workarounds) is attached below.

While investigating why the test was failing I stumbled across
a few problems:

+ MapViewOfFileEx() was failing with ERROR_MAPPED_ALIGNMENT (1132)
  because the base address is supposed to be a multiple of the
  memory allocation granularity, which is
  SYSTEM_INFO.dwAllocationGranularity or 64k.  But, the test logic
  aligns on getpagesize() boundaries, which is
  SYSTEM_INFO.dwPageSize or 4k.

+ After working around this (pagesize = 65536), MapViewOfFileEx()
  started failing with ERROR_INVALID_ADDRESS (487), which means
  that you can't map over an address already allocated by VirtualAlloc().
  By making sure the address is past anything already allocated
  (data2 += 10000 * pagesize) the test succeeds.

  I also tried releasing the underlying memory with VirtualFree(),
  but this only works if you decommit/release the same range of
  pages originally allocated with VirtualAlloc(), and any fix here
  required some significant changes to heap.cc.

I wasn't able to find any prior discussion of these issues.  Are these
known problems?

This isn't a big deal, because in the end Apache doesn't use
MAP_FIXED (only configure does).

Thanks.

Eric

--

#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

char *malloc();

int
main()
{
	char *data, *data2, *data3;
	int i, pagesize;
	int fd;

	pagesize = getpagesize();
	pagesize = 65536; /* WORKAROUND 1 */

	/*
	 * First, make a file with some known garbage in it.
	 */
	data = malloc(pagesize);
	if (!data)
		exit(1);
	for (i = 0; i < pagesize; ++i)
		*(data + i) = rand();
	umask(0);
	fd = creat("conftestmmap", 0600);
	if (fd < 0)
		exit(1);
	if (write(fd, data, pagesize) != pagesize)
		exit(1);
	close(fd);

	/*
	 * Next, try to mmap the file at a fixed address which
	 * already has something else allocated at it.  If we can,
	 * also make sure that we see the same garbage.
	 */
	fd = open("conftestmmap", O_RDWR);
	if (fd < 0)
		exit(1);
	data2 = malloc(2 * pagesize);
	data2 += 10000 * pagesize; /* WORKAROUND 2 */
	if (!data2)
		exit(1);
	data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize -
1);
	if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_FIXED, fd, 0L))
		exit(1);
	for (i = 0; i < pagesize; ++i)
		if (*(data + i) != *(data2 + i))
			exit(1);

	/*
	 * Finally, make sure that changes to the mapped area
	 * do not percolate back to the file as seen by read().
	 * (This is a bug on some variants of i386 svr4.0.)
	 */
	for (i = 0; i < pagesize; ++i)
		*(data2 + i) = *(data2 + i) + 1;
	data3 = malloc(pagesize);
	if (!data3)
		exit(1);
	if (read(fd, data3, pagesize) != pagesize)
		exit(1);
	for (i = 0; i < pagesize; ++i)
		if (*(data + i) != *(data3 + i))
			exit(1);
	close(fd);
	unlink("conftestmmap");
	exit(0);
}

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