Web lists-archives.com

Re: Atomic mmap replacement

On 2/19/2018 4:00 AM, Corinna Vinschen wrote:
On Feb 17 22:37, Ken Brown wrote:
Some code in emacs wants to reserve a chunk of address space with a big
PROT_NONE anonymous mapping, and then carve it up into separate mappings
associated to segments of a file.  This fails on Cygwin.  Here's a test case
that illustrates the problem:

$ truncate -s 64k foo

$ cat mmap_test.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>

const size_t page_size = 64 * 1024;

main ()
   void *mem = mmap (NULL, 2 * page_size,
                     PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (mem == MAP_FAILED)
       perror ("mmap");
       exit (1);
   int fd = open ("foo", O_RDONLY);
   void *res = mmap (mem, page_size, PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_FIXED, fd, 0);
   if (res == MAP_FAILED)
       perror ("mmap");
       exit (2);

$ gcc mmap_test.c

$ ./a
mmap: Invalid argument

$ echo $?

Is this a bug, or is it simply a limitation of Cygwin's mmap?  If the
latter, is there a simple workaround?

Several limitations in the Windows kernel disallow this:

- It doesn't allow to unmap parts of a map, only the entire map as a
Cygwin has a workaround: If you unmap parts of a map it just keeps
   track of this and sets the protection of the affected pages to
   PAGE_NOACCESS.  In case of anonymous mappings, it even recycles them
   potentially for other mappings.

- It also disallows to re-map any allocated or mapped mamory for another

So this part of the POSIX specs for mmap:

   "The mapping established by mmap() shall replace any previous mappings
    for those whole pages containing any part of the address space of the
    process starting at pa and continuing for len bytes"

can't be implemented with Windows means.

The only workaround possible would be to handle this *exact* scenario as
a special case in Cygwin's mmap:  If the new mapping falls in the middle
of an existing mapping and if the original mapping was an anonymous
mapping with PROT_NONE page protection, then

- unmap the old mapping
- remap the unaffected parts as separate anonymous mapping
- map the affected parts for the requested file mapping

This is pretty complicated and I'm not hot on implementing it.  If it's
really required we can take a look of course.

Thanks, Corinna.  I'll take this information back to the emacs list.


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