This is the mail archive of the cygwin 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]
Other format: [Raw text]

Re: Atomic mmap replacement


On 2/19/2018 12:19 PM, Corinna Vinschen wrote:
On Feb 19 08:22, Ken Brown wrote:
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:
[...]
Several limitations in the Windows kernel disallow this:

- It doesn't allow to unmap parts of a map, only the entire map as a
    whole.
    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
    purpose.

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

On second thought, we *could* do this, if the pages have been mmapped
before(*).  Unfortunately this would require a *major* revamp of the
page handling in mmap.  We would have to keep the mapping of every
single 64K page separate.

I.e., requesting a file mapping of 256K at offset 0 on the POSIX level
would have to be handled as four Windows file mappings under the hood:

1. a 64K file mapping at offset 0
2. a 64K file mapping at offset 65536
3. a 64K file mapping at offset 131072
4. a 64K file mapping at offset 196608

A request to mmap another 64K page to the third mapping in this example
could then be done by unmapping the third mapping and replace it with
the requested mapping.

I'm not sure this is feasible.  It would complicate and slow down the
code especially for big mappings; one call to NtCreateSection and one to
NtMapViewOfSection per 64K page, plus the overhead of making sure that
all mappings are in the right, sequential order in memory.  Plus the
overhead of having to remap a lot more mappings in forked children.  The
"Cygwin is slow" meme would get another interesting facet :}

That doesn't sound great.

In the meantime, the problem was solved on the emacs side by doing what you suggested in your previous email:

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

But in the emacs application it's simpler, because there are no unaffected parts, so step 2 can be skipped.

Thanks.

Ken

--
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


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