On Dec 21 19:05, Ken Brown wrote:
> Hi Mark,
> 
> On 12/21/2024 5:15 PM, Mark Geisert wrote:
> > Hi Ken,
> > 
> > On 12/21/2024 1:42 PM, Ken Brown wrote:
> > > I'm wondering why munmap insists on operating with chunks of size
> > > 64k instead of pages of size 4k.  In other words, what would go
> > > wrong if we did the following:

It would be wrong.

> > > 
> > > --- a/winsup/cygwin/mm/mmap.cc
> > > +++ b/winsup/cygwin/mm/mmap.cc
> > > @@ -1143,7 +1143,7 @@ munmap (void *addr, size_t len)
> > >         set_errno (EINVAL);
> > >         return -1;
> > >       }
> > > -  const size_t pagesize = wincap.allocation_granularity ();
> > > +  const size_t pagesize = wincap.page_size ();
> > >     if (((uintptr_t) addr % pagesize) || !len)
> > >       {
> > >         set_errno (EINVAL);
> > > 
> > > I'm currently testing a build with this patch, and so far I haven't
> > > seen any problems.  But maybe I don't know what to test.
> > 
> > I'm afraid I don't remember the circumstances, but the change from 4K
> > pages to 64K was done somewhat recently.  In the last 2-3 years IIRC.
> > 
> > Maybe check the git history of mmap.cc for clues?  Some corner case of
> > how Windows manages page protection wasn't allowing the desired POSIX
> > and/or Linux behavior?
> Good suggestion.  The following commit changed getpagesize() to return 64k
> instead of 4k [and it makes the opposite change for getsystempagesize()],
> but the commit message doesn't say why:
> 
> commit 1656b946379942d5a7d78afdaf9786b78b7b618b
> Author: Corinna Vinschen <cori...@vinschen.de>
> Date:   Tue Jan 9 15:46:41 2007 +0000
> 
>             * syscalls.cc (getpagesize): Change condition for clarity.
>             (getsystempagesize): Ditto.
> 
> And munmap used getpagesize() to determine its page size for a long time,
> which means that the munmap page size changed from 4k to 64k after the above
> commit.

No, the patch introducing the 64K pagesize was f90e23f2714c ("*
external.cc (cygwin_internal): Call getpagesize instead of getshmlba.")

> I don't know the rationale for that change.

The point was that a pagesize of 4K is wrong from the POSIX point of
view.  I was pretty stubborn in understanding this myself, and it
took quite some time until I caved in and produced the aforementioned
patch back in 2005.

The reason (or rather, one example) is that you can't do this:

  fd = open ("file1", O_RDONLY);

  addr1 = mmap (NULL, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  addr2 = mmap (addr1 + 4096, 4096, PROT_READ, MAP_PRIVATE, fd, 0);

This fails on Windows because the allocation granularity is 64K.  So
even though the mapping at addr1 is (supposedly) only one pagesize of 4K
in size...

- the entire region [addr1,addr1+64K[ is now blocked for other mappings,
  and

- a mapping can only start at an address % 64K, so the "addr1+4096"
  expression doesn't work on Windows, because the mapping can only
  start at the next (or any other) 64K boundary.

Multiple assumptions around file mappings differ between Windows
and POSIX, and the most sane way to emulate POSIX on Windows in this
respect is to define the POSIX pagesize as the Windows allocation
granularity.


Corinna

Reply via email to