Subject: Re: mmap bug on Windows 9x
From: "Anton Ertl" <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Date: Fri, 16 Jul 2004 09:12:09 +0200 (CEST)

Anton Ertl wrote:
> 
> On Windows 9x/ME different calls to mmap sometimes produce the same
> address (without that memory being unmapped in the meantime, at least
> not by application code).

You find a condensed test program below.

On Windows ME with cygwin1.dll 1.5.10 it outputs:

try mmap($0, $40000, ..., MAP_ANON, ...); success, address=$833ca000
try mmap($8340b000, $40000, ..., MAP_ANON, ...); success, address=$833ca000

Note that the result addresses are the same.

On Windows 2000 with cygwin1.dll 1.3.22 it outputs:

try mmap($0, $40000, ..., MAP_ANON, ...); success, address=$640000
try mmap($681000, $40000, ..., MAP_ANON, ...); success, address=$680000

i.e., non-overlapping memory ranges, as it should.

I believe that this is a problem that both cygwin1.dlls have on
Windows ME/9x (and not on NT/2K/XP), not something arising from the
difference between cygwin versions (we see a problem that probably
arises from this bug also with the Gforth-for-Windows package that
includes cygwin1.dll 1.3.22).

- anton

Here's the test program (compile and run with "gcc -O main.c; ./a):
-----------------------------------------------------
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#ifndef STANDALONE
#include <sys/stat.h>
#endif
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#ifndef STANDALONE
#include <sys/mman.h>
#endif

int debug=1;
#define HAVE_MMAP
typedef char *Address;
typedef int Cell;
int pagesize=4096;

static Address next_address=0;
void after_alloc(Address r, Cell size)
{
  if (r != (Address)-1) {
    if (debug)
      fprintf(stderr, "success, address=$%lx\n", (long) r);
    if (pagesize != 1)
      next_address = (Address)(((((Cell)r)+size-1)&-pagesize)+2*pagesize); /* leave one page unmapped */
  } else {
    if (debug)
      fprintf(stderr, "failed: %s\n", strerror(errno));
  }
}

#ifndef MAP_FAILED
#define MAP_FAILED ((Address) -1)
#endif
#ifndef MAP_FILE
# define MAP_FILE 0
#endif
#ifndef MAP_PRIVATE
# define MAP_PRIVATE 0
#endif
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
# define MAP_ANON MAP_ANONYMOUS
#endif

#if defined(HAVE_MMAP)
static Address alloc_mmap(Cell size)
{
  Address r;

#if defined(MAP_ANON)
  if (debug)
    fprintf(stderr,"try mmap($%lx, $%lx, ..., MAP_ANON, ...); ", (long)next_address, (long)size);
  r = mmap(next_address, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
#else /* !defined(MAP_ANON) */
  /* Ultrix (at least) does not define MAP_FILE and MAP_PRIVATE (both are
     apparently defaults) */
  static int dev_zero=-1;

  if (dev_zero == -1)
    dev_zero = open("/dev/zero", O_RDONLY);
  if (dev_zero == -1) {
    r = MAP_FAILED;
    if (debug)
      fprintf(stderr, "open(\"/dev/zero\"...) failed (%s), no mmap; ", 
	      strerror(errno));
  } else {
    if (debug)
      fprintf(stderr,"try mmap($%lx, $%lx, ..., MAP_FILE, dev_zero, ...); ", (long)next_address, (long)size);
    r=mmap(next_address, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, dev_zero, 0);
  }
#endif /* !defined(MAP_ANON) */
  after_alloc(r, size);
  return r;  
}
#endif

int main(int argc, char **argv, char **env)
{
  debug=1;
  alloc_mmap(0x40000);
  alloc_mmap(0x40000);
  exit(0);
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/