Patches attached.

Ken Brown (5):
  Cygwin: mmap: refactor mmap_record::match
  Cygwin: mmap: remove is_mmapped_region()
  Cygwin: mmap: remove __PROT_FILLER and the associated methods
  Cygwin: mmap_list::try_map: simplify
  Cygwin: remove winsup/cygwin/local_includes/mmap_helper.h

 winsup/cygwin/local_includes/mmap_helper.h |  89 ---------------
 winsup/cygwin/local_includes/winsup.h      |   1 -
 winsup/cygwin/mm/mmap.cc                   | 126 +++++++--------------
 3 files changed, 44 insertions(+), 172 deletions(-)
 delete mode 100644 winsup/cygwin/local_includes/mmap_helper.h

--
2.45.1
From 4387a73d5593ddad4cf7592865b5b257e6a9d6de Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Fri, 27 Dec 2024 15:30:12 -0500
Subject: [PATCH 1/5] Cygwin: mmap: refactor mmap_record::match

Slightly simplify the code and add comments to explain what the
function does.  Add a new reference parameter "contains" that is set
to true if the chunk of this mmap_record contains the given address
range.

Signed-off-by: Ken Brown <kbr...@cornell.edu>
---
 winsup/cygwin/mm/mmap.cc | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc
index 0224779458ef..acab85d19cf0 100644
--- a/winsup/cygwin/mm/mmap.cc
+++ b/winsup/cygwin/mm/mmap.cc
@@ -338,7 +338,8 @@ class mmap_record
     void init_page_map (mmap_record &r);
 
     SIZE_T find_unused_pages (SIZE_T pages) const;
-    bool match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len);
+    bool match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len,
+                bool &contains);
     off_t map_pages (SIZE_T len, int new_prot);
     bool map_pages (caddr_t addr, SIZE_T len, int new_prot);
     bool unmap_pages (caddr_t addr, SIZE_T len);
@@ -418,20 +419,30 @@ mmap_record::find_unused_pages (SIZE_T pages) const
   return (SIZE_T) -1;
 }
 
+/* Return true if the interval I from addr to addr + len intersects
+   the interval J of this mmap_record.  The endpoint of the latter is
+   first rounded up to a page boundary.  If there is an intersection,
+   then it is the interval from m_addr to m_addr + m_len.  The
+   variable 'contains' is set to true if J contains I.
+*/
 bool
-mmap_record::match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len)
+mmap_record::match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len,
+                   bool &contains)
 {
-  caddr_t low = (addr >= get_address ()) ? addr : get_address ();
+  contains = false;
+  caddr_t low = MAX (addr, get_address ());
   caddr_t high = get_address ();
   if (filler ())
     high += get_len ();
   else
     high += (PAGE_CNT (get_len ()) * wincap.page_size ());
-  high = (addr + len < high) ? addr + len : high;
+  high = MIN (addr + len, high);
   if (low < high)
     {
       m_addr = low;
       m_len = high - low;
+      /* I is contained in J iff their intersection equals I. */
+      contains = (addr == m_addr && len == m_len);
       return true;
     }
   return false;
@@ -653,14 +664,14 @@ mmap_list::try_map (void *addr, size_t len, int new_prot, 
int flags, off_t off)
         request, try to reset the protection on the requested area. */
       caddr_t u_addr;
       SIZE_T u_len;
+      bool contains;
 
       LIST_FOREACH (rec, &recs, mr_next)
-       if (rec->match ((caddr_t) addr, len, u_addr, u_len))
+       if (rec->match ((caddr_t) addr, len, u_addr, u_len, contains))
          break;
       if (rec)
        {
-         if (u_addr > (caddr_t) addr || u_addr + u_len < (caddr_t) addr + len
-             || !rec->compatible_flags (flags))
+         if (!contains || !rec->compatible_flags (flags))
            {
              /* Partial match only, or access mode doesn't match. */
              /* FIXME: Handle partial mappings gracefully if adjacent
@@ -730,11 +741,12 @@ is_mmapped_region (caddr_t start_addr, caddr_t 
end_address)
   mmap_record *rec;
   caddr_t u_addr;
   SIZE_T u_len;
+  bool contains;
   bool ret = false;
 
   LIST_FOREACH (rec, &map_list->recs, mr_next)
     {
-      if (rec->match (start_addr, len, u_addr, u_len))
+      if (rec->match (start_addr, len, u_addr, u_len, contains))
        {
          ret = true;
          break;
@@ -786,10 +798,11 @@ mmap_is_attached_or_noreserve (void *addr, size_t len)
 
   if (map_list == NULL)
     goto out;
+  bool contains;
 
   LIST_FOREACH (rec, &map_list->recs, mr_next)
     {
-      if (!rec->match (start_addr, len, u_addr, u_len))
+      if (!rec->match (start_addr, len, u_addr, u_len, contains))
        continue;
       if (rec->attached ())
        {
@@ -1177,10 +1190,11 @@ munmap (void *addr, size_t len)
       mmap_record *rec, *next_rec;
       caddr_t u_addr;
       SIZE_T u_len;
+      bool contains;
 
       LIST_FOREACH_SAFE (rec, &map_list->recs, mr_next, next_rec)
        {
-         if (!rec->match ((caddr_t) addr, len, u_addr, u_len))
+         if (!rec->match ((caddr_t) addr, len, u_addr, u_len, contains))
            continue;
          if (rec->unmap_pages (u_addr, u_len))
            {
@@ -1299,10 +1313,11 @@ mprotect (void *addr, size_t len, int prot)
       mmap_record *rec;
       caddr_t u_addr;
       SIZE_T u_len;
+      bool contains;
 
       LIST_FOREACH (rec, &map_list->recs, mr_next)
        {
-         if (!rec->match ((caddr_t) addr, len, u_addr, u_len))
+         if (!rec->match ((caddr_t) addr, len, u_addr, u_len, contains))
            continue;
          in_mapped = true;
          if (rec->attached ())
-- 
2.45.1

From d3c62d48f87044d7607d81559c58ae06df5839af Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Fri, 20 Dec 2024 12:17:34 -0500
Subject: [PATCH 2/5] Cygwin: mmap: remove is_mmapped_region()

The last use was removed in commit 29a126322783 ("Simplify stack
allocation code in child after fork").

Signed-off-by: Ken Brown <kbr...@cornell.edu>
---
 winsup/cygwin/local_includes/winsup.h |  1 -
 winsup/cygwin/mm/mmap.cc              | 34 ---------------------------
 2 files changed, 35 deletions(-)

diff --git a/winsup/cygwin/local_includes/winsup.h 
b/winsup/cygwin/local_includes/winsup.h
index 38313962d96c..6841d4a59fb4 100644
--- a/winsup/cygwin/local_includes/winsup.h
+++ b/winsup/cygwin/local_includes/winsup.h
@@ -239,7 +239,6 @@ enum mmap_region_status
     MMAP_NORESERVE_COMMITED
   };
 mmap_region_status mmap_is_attached_or_noreserve (void *addr, size_t len);
-bool is_mmapped_region (caddr_t start_addr, caddr_t end_address);
 
 extern inline bool flush_file_buffers (HANDLE h)
 {
diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc
index acab85d19cf0..13e64c23256c 100644
--- a/winsup/cygwin/mm/mmap.cc
+++ b/winsup/cygwin/mm/mmap.cc
@@ -722,40 +722,6 @@ mmap_areas::del_list (mmap_list *ml)
   cfree (ml);
 }
 
-/* This function allows an external function to test if a given memory
-   region is part of an mmapped memory region. */
-bool
-is_mmapped_region (caddr_t start_addr, caddr_t end_address)
-{
-  size_t len = end_address - start_addr;
-
-  LIST_READ_LOCK ();
-  mmap_list *map_list = mmapped_areas.get_list_by_fd (-1, NULL);
-
-  if (!map_list)
-    {
-      LIST_READ_UNLOCK ();
-      return false;
-    }
-
-  mmap_record *rec;
-  caddr_t u_addr;
-  SIZE_T u_len;
-  bool contains;
-  bool ret = false;
-
-  LIST_FOREACH (rec, &map_list->recs, mr_next)
-    {
-      if (rec->match (start_addr, len, u_addr, u_len, contains))
-       {
-         ret = true;
-         break;
-       }
-    }
-  LIST_READ_UNLOCK ();
-  return ret;
-}
-
 /* This function is called from exception_handler when a segmentation
    violation has occurred.  It should also be called from all Cygwin
    functions that want to support passing noreserve (anonymous) mmap
-- 
2.45.1

From 87e07edb7c53f425c86579d013d29efd3f905203 Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Fri, 20 Dec 2024 13:11:22 -0500
Subject: [PATCH 3/5] Cygwin: mmap: remove __PROT_FILLER and the associated
 methods

This is left over from 32 bit Cygwin and is no longer used.

Signed-off-by: Ken Brown <kbr...@cornell.edu>
---
 winsup/cygwin/mm/mmap.cc | 31 +++++++------------------------
 1 file changed, 7 insertions(+), 24 deletions(-)

diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc
index 13e64c23256c..9e6415de9951 100644
--- a/winsup/cygwin/mm/mmap.cc
+++ b/winsup/cygwin/mm/mmap.cc
@@ -27,14 +27,8 @@ details. */
    is to support mappings longer than the file, without the file growing
    to mapping length (POSIX semantics). */
 #define __PROT_ATTACH   0x8000000
-/* Filler pages are the pages from the last file backed page to the next
-   64K boundary.  These pages are created as anonymous pages, but with
-   the same page protection as the file's pages, since POSIX applications
-   expect to be able to access this part the same way as the file pages. */
-#define __PROT_FILLER   0x4000000
-
-/* Stick with 4K pages for bookkeeping, otherwise we just get confused
-   when trying to do file mappings with trailing filler pages correctly. */
+
+/* Stick with 4K pages for bookkeeping. */
 #define PAGE_CNT(bytes) howmany((bytes), wincap.page_size())
 
 #define PGBITS         (sizeof (DWORD)*8)
@@ -91,12 +85,6 @@ attached (int prot)
   return (prot & __PROT_ATTACH) == __PROT_ATTACH;
 }
 
-static inline bool
-filler (int prot)
-{
-  return (prot & __PROT_FILLER) == __PROT_FILLER;
-}
-
 static inline DWORD
 gen_create_protect (DWORD openflags, int flags)
 {
@@ -125,7 +113,7 @@ gen_protect (int prot, int flags)
     return PAGE_EXECUTE_READWRITE;
 
   if (prot & PROT_WRITE)
-    ret = (priv (flags) && (!anonymous (flags) || filler (prot)))
+    ret = (priv (flags) && !anonymous (flags))
          ? PAGE_WRITECOPY : PAGE_READWRITE;
   else if (prot & PROT_READ)
     ret = PAGE_READONLY;
@@ -330,7 +318,6 @@ class mmap_record
     bool noreserve () const { return ::noreserve (flags); }
     bool autogrow () const { return ::autogrow (flags); }
     bool attached () const { return ::attached (prot); }
-    bool filler () const { return ::filler (prot); }
     off_t get_offset () const { return offset; }
     SIZE_T get_len () const { return len; }
     caddr_t get_address () const { return base_address; }
@@ -430,13 +417,9 @@ mmap_record::match (caddr_t addr, SIZE_T len, caddr_t 
&m_addr, SIZE_T &m_len,
                    bool &contains)
 {
   contains = false;
+  SIZE_T rec_len = PAGE_CNT (get_len ()) * wincap.page_size ();
   caddr_t low = MAX (addr, get_address ());
-  caddr_t high = get_address ();
-  if (filler ())
-    high += get_len ();
-  else
-    high += (PAGE_CNT (get_len ()) * wincap.page_size ());
-  high = MIN (addr + len, high);
+  caddr_t high = MIN (addr + len, get_address () + rec_len);
   if (low < high)
     {
       m_addr = low;
@@ -1569,7 +1552,7 @@ fhandler_dev_zero::mmap (caddr_t *addr, size_t len, int 
prot,
   HANDLE h;
   void *base;
 
-  if (priv (flags) && !filler (prot))
+  if (priv (flags))
     {
       /* Private anonymous maps are now implemented using VirtualAlloc.
         This has two advantages:
@@ -1678,7 +1661,7 @@ fhandler_dev_zero::fixup_mmap_after_fork (HANDLE h, int 
prot, int flags,
 {
   /* Re-create the map */
   void *base;
-  if (priv (flags) && !filler (prot))
+  if (priv (flags))
     {
       DWORD alloc_type = MEM_RESERVE | (noreserve (flags) ? 0 : MEM_COMMIT);
       /* Always allocate R/W so that ReadProcessMemory doesn't fail
-- 
2.45.1

From c01da9db1e76869621b63f8075505fa49acf0d56 Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Sun, 29 Dec 2024 18:20:07 -0500
Subject: [PATCH 4/5] Cygwin: mmap_list::try_map: simplify

Save the result of mmap_record::find_unused pages, and then pass that
result to the appropriate version of mmap_record::map_pages.  Add a
new parameter of type off_t to the latter to make this possible, and
change its return from off_t to bool.  This saves map_pages from
having to call find_unused_pages again.

Signed-off-by: Ken Brown <kbr...@cornell.edu>
---
 winsup/cygwin/mm/mmap.cc | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc
index 9e6415de9951..9ed9131771d7 100644
--- a/winsup/cygwin/mm/mmap.cc
+++ b/winsup/cygwin/mm/mmap.cc
@@ -327,7 +327,7 @@ class mmap_record
     SIZE_T find_unused_pages (SIZE_T pages) const;
     bool match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len,
                 bool &contains);
-    off_t map_pages (SIZE_T len, int new_prot);
+    bool map_pages (SIZE_T len, int new_prot, off_t off);
     bool map_pages (caddr_t addr, SIZE_T len, int new_prot);
     bool unmap_pages (caddr_t addr, SIZE_T len);
     int access (caddr_t address);
@@ -449,21 +449,18 @@ mmap_record::init_page_map (mmap_record &r)
     MAP_SET (len);
 }
 
-off_t
-mmap_record::map_pages (SIZE_T len, int new_prot)
+bool
+mmap_record::map_pages (SIZE_T len, int new_prot, off_t off)
 {
-  /* Used ONLY if this mapping matches into the chunk of another already
-     performed mapping in a special case of MAP_ANON|MAP_PRIVATE.
-
-     Otherwise it's job is now done by init_page_map(). */
+  /* Used only in a MAP_ANON|MAP_PRIVATE request for len bytes, with
+     MAP_FIXED not given.  Moreover, we know when this function is
+     called that this record contains enough unused pages starting at
+     off to satisfy the request. */
   DWORD old_prot;
   debug_printf ("map_pages (fd=%d, len=%lu, new_prot=%y)", get_fd (), len,
                new_prot);
   len = PAGE_CNT (len);
 
-  off_t off = find_unused_pages (len);
-  if (off == (off_t) -1)
-    return (off_t) 0;
   if (!noreserve ()
       && !VirtualProtect (get_address () + off * wincap.page_size (),
                          len * wincap.page_size (),
@@ -471,12 +468,12 @@ mmap_record::map_pages (SIZE_T len, int new_prot)
                          &old_prot))
     {
       __seterrno ();
-      return (off_t) -1;
+      return false;
     }
 
   while (len-- > 0)
     MAP_SET (off + len);
-  return off * wincap.page_size ();
+  return true;
 }
 
 bool
@@ -630,13 +627,14 @@ mmap_list::try_map (void *addr, size_t len, int new_prot, 
int flags, off_t off)
         mapping. */
       SIZE_T plen = PAGE_CNT (len);
       LIST_FOREACH (rec, &recs, mr_next)
-       if (rec->find_unused_pages (plen) != (SIZE_T) -1)
+       if ((off = rec->find_unused_pages (plen)) != (off_t) -1
+           && rec->compatible_flags (flags))
          break;
-      if (rec && rec->compatible_flags (flags))
+      if (rec)
        {
-         if ((off = rec->map_pages (len, new_prot)) == (off_t) -1)
+         if (!rec->map_pages (len, new_prot, off))
            return (caddr_t) MAP_FAILED;
-         return (caddr_t) rec->get_address () + off;
+         return (caddr_t) rec->get_address () + off * wincap.page_size ();
        }
     }
   else if (fixed (flags))
-- 
2.45.1

From 8c3a918c346a9ae97e219679d780c9b716588fc8 Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Sun, 29 Dec 2024 18:47:54 -0500
Subject: [PATCH 5/5] Cygwin: remove winsup/cygwin/local_includes/mmap_helper.h

None of its macros and functions are used anymore.

Signed-off-by: Ken Brown <kbr...@cornell.edu>
---
 winsup/cygwin/local_includes/mmap_helper.h | 89 ----------------------
 1 file changed, 89 deletions(-)
 delete mode 100644 winsup/cygwin/local_includes/mmap_helper.h

diff --git a/winsup/cygwin/local_includes/mmap_helper.h 
b/winsup/cygwin/local_includes/mmap_helper.h
deleted file mode 100644
index 645c5e3aac84..000000000000
--- a/winsup/cygwin/local_includes/mmap_helper.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* mmap_helper.h
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#ifndef _MMAP_HELPER_H
-#define _MMAP_HELPER_H
-#define _MMIOWRAP(__ptr, __len, __func) \
-({ \
-  BOOL __res; \
-  for (int __i = 0; __i < 2; __i++) \
-    { \
-      __res = __func; \
-      if (__res || __i > 0) \
-       break; \
-      DWORD __errcode = GetLastError (); \
-      if (__errcode != ERROR_NOACCESS) \
-       break; \
-      switch (mmap_is_attached_or_noreserve (__ptr, __len)) \
-       { \
-       case MMAP_NORESERVE_COMMITED: \
-         continue; \
-       case MMAP_RAISE_SIGBUS: \
-         raise(SIGBUS); \
-       default: \
-         break; \
-       } \
-      break; \
-    } \
-  __res; \
-})
-
-#define _MMSOCKWRAP(__ptr, __count, __func) \
-({ \
-  int __res; \
-  for (int __i = 0; __i < 2; __i++) \
-    { \
-      __res = __func; \
-      if (!__res || __i > 0) \
-       break; \
-      DWORD __errcode = WSAGetLastError (); \
-      if (__errcode != WSAEFAULT) \
-       break; \
-      for (unsigned __j = 0; __j < __count; __j++) \
-       switch (mmap_is_attached_or_noreserve (__ptr[__j].buf, __ptr[__j].len)) 
\
-         { \
-         case MMAP_NORESERVE_COMMITED: \
-           goto keeptrying; \
-         case MMAP_RAISE_SIGBUS: \
-           raise(SIGBUS); \
-         default: \
-           break; \
-         } \
-      break; \
-    keeptrying: \
-      continue; \
-    } \
-  __res; \
-})
-
-extern inline BOOL
-mmReadFile (HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
-           LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
-{
-  return _MMIOWRAP (lpBuffer, nNumberOfBytesToRead,
-                   (ReadFile (hFile, lpBuffer, nNumberOfBytesToRead,
-                              lpNumberOfBytesRead, lpOverlapped)));
-}
-
-#ifdef _WINSOCK_H
-extern inline int
-mmWSARecvFrom (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
-           LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
-           struct sockaddr* lpFrom,
-           LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
-           LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
-{
-  return _MMSOCKWRAP (lpBuffers, dwBufferCount,
-                     (mmWSARecvFrom(s, lpBuffers, dwBufferCount,
-                                    lpNumberOfBytesRecvd, lpFlags, lpFrom,
-                                    lpFromlen, lpOverlapped,
-                                    lpCompletionRoutine)));
-}
-#endif /*_WINSOCK_H*/
-
-#endif /*_MMAP_HELPER_H*/
-- 
2.45.1

Reply via email to