OSDN Git Service

* exceptions.cc (_cygtls::handle_exceptions): Call new
authorcorinna <corinna>
Thu, 13 Jul 2006 08:33:34 +0000 (08:33 +0000)
committercorinna <corinna>
Thu, 13 Jul 2006 08:33:34 +0000 (08:33 +0000)
mmap_is_attached_or_noreserve_page function in case of access violation
and allow application to retry access on noreserve pages.
* mmap.cc (mmap_is_attached_or_noreserve_page): Changed from
mmap_is_attached_page.  Handle also noreserve pages now.  Change
comment accordingly.
* winsup.h (mmap_is_attached_or_noreserve_page): Declare instead of
mmap_is_attached_page.

winsup/cygwin/ChangeLog
winsup/cygwin/exceptions.cc
winsup/cygwin/mmap.cc
winsup/cygwin/winsup.h

index 0ff39df..0a3b7c2 100644 (file)
@@ -1,3 +1,14 @@
+2006-07-13  Corinna Vinschen  <corinna@vinschen.de>
+
+       * exceptions.cc (_cygtls::handle_exceptions): Call new
+       mmap_is_attached_or_noreserve_page function in case of access violation
+       and allow application to retry access on noreserve pages.
+       * mmap.cc (mmap_is_attached_or_noreserve_page): Changed from
+       mmap_is_attached_page.  Handle also noreserve pages now.  Change
+       comment accordingly.
+       * winsup.h (mmap_is_attached_or_noreserve_page): Declare instead of
+       mmap_is_attached_page.
+
 2006-07-12  Corinna Vinschen  <corinna@vinschen.de>
 
        * mmap.cc (mmap_record::alloc_page_map): Don't call VirtualProtect
index 4d078dd..12c6e06 100644 (file)
@@ -526,17 +526,21 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
       break;
 
     case STATUS_ACCESS_VIOLATION:
-      if (mmap_is_attached_page (e->ExceptionInformation[1]))
-       {
+      switch (mmap_is_attached_or_noreserve_page (e->ExceptionInformation[1]))
+        {
+       case 2:         /* MAP_NORESERVE page, now commited. */
+         return 0;
+       case 1:         /* MAP_NORESERVE page, commit failed, or
+                          access to mmap page beyond EOF. */
          si.si_signo = SIGBUS;
          si.si_code = BUS_OBJERR;
-       }
-      else
-       {
+         break;
+       default:
          MEMORY_BASIC_INFORMATION m;
          VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
          si.si_signo = SIGSEGV;
          si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
+         break;
        }
       break;
 
index 7ca176c..193ed7c 100644 (file)
@@ -900,13 +900,25 @@ map::del_list (unsigned i)
 }
 
 /* This function is called from exception_handler when a segmentation
-   violation has happened.  The function should return true, if the
-   faulting address (the parameter) is within attached pages.  In this
-   case the exception_handler raises SIGBUS, as demanded by the memory
-   protection extension described in SUSv3 (see the mmap man page).
-   If false is returned, a normal SIGSEGV is raised. */
-bool
-mmap_is_attached_page (ULONG_PTR addr)
+   violation has happened.  We have two cases to check here.
+   
+   First, is it an address within "attached" mmap pages (indicated by
+   the __PROT_ATTACH protection, see there)?  In this case the function
+   returns 1 and the exception_handler raises SIGBUS, as demanded by the
+   memory protection extension described in SUSv3 (see the mmap man
+   page).
+   
+   Second, check if the address is within "noreserve" mmap pages
+   (indicated by MAP_NORESERVE flag).  If so, the function calls
+   VirtualAlloc to commit the page and returns 2.  The exception handler
+   then just returns with 0 and the affected application retries the
+   failing memory access.  If VirtualAlloc fails, the function returns
+   1, so that the exception handler raises a SIGBUS, as described in the
+   MAP_NORESERVE man pages for Linux and Solaris.
+   
+   In any other case 0 is returned and a normal SIGSEGV is raised. */
+int
+mmap_is_attached_or_noreserve_page (ULONG_PTR addr)
 {
   list *map_list;
   long record_idx;
@@ -916,13 +928,16 @@ mmap_is_attached_page (ULONG_PTR addr)
 
   addr = rounddown (addr, pagesize);
   if (!(map_list = mmapped_areas.get_list_by_fd (-1)))
-    return false;
+    return 0;
   if ((record_idx = map_list->search_record ((caddr_t)addr, pagesize,
                                             u_addr, u_len, -1)) < 0)
-    return false;
-  if (!map_list->get_record (record_idx)->attached ())
-    return false;
-  return true;
+    return 0;
+  if (map_list->get_record (record_idx)->attached ())
+    return 1;
+  if (!map_list->get_record (record_idx)->noreserve ())
+    return 0;
+  DWORD new_prot = map_list->get_record (record_idx)->gen_protect ();
+  return VirtualAlloc ((void *)addr, pagesize, MEM_COMMIT, new_prot) ? 2 : 1;
 }
 
 static caddr_t
index 9a1039d..7271514 100644 (file)
@@ -299,7 +299,7 @@ size_t getsystempagesize ();
 
 /* mmap functions. */
 void mmap_init ();
-bool mmap_is_attached_page (ULONG_PTR);
+int mmap_is_attached_or_noreserve_page (ULONG_PTR addr);
 
 int winprio_to_nice (DWORD) __attribute__ ((regparm (1)));
 DWORD nice_to_winprio (int &) __attribute__ ((regparm (1)));