aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-07-13 08:34:54 +0000
committerCorinna Vinschen <corinna@vinschen.de>2006-07-13 08:34:54 +0000
commitc7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd (patch)
treec5a5794c13d6c6554b1db5550cb1481784f0f25c
parent202f17bca50a9f5dde2fad655a8ef838e89a1e4c (diff)
downloadnewlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.zip
newlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.tar.gz
newlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.tar.bz2
* Merge HEAD into cv-branch.
-rw-r--r--winsup/cygwin/ChangeLog16
-rw-r--r--winsup/cygwin/exceptions.cc14
-rw-r--r--winsup/cygwin/mmap.cc41
-rw-r--r--winsup/cygwin/winsup.h2
4 files changed, 54 insertions, 19 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 30bfa92..f63f111 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,19 @@
+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
+ on maps created with MAP_NORESERVE.
+
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* include/netdb.h: Declare rcmd, rcmd_af, rexec, rresvport,
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 4d078dd..12c6e06 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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;
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index cee1a81..193ed7c 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -574,7 +574,7 @@ mmap_record::alloc_page_map ()
DWORD start_protect = gen_create_protect ();
DWORD real_protect = gen_protect ();
- if (real_protect != start_protect
+ if (real_protect != start_protect && !noreserve ()
&& !VirtualProtect (get_address (), get_len (),
real_protect, &start_protect))
system_printf ("Warning: VirtualProtect (addr: %p, len: 0x%x, "
@@ -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
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 9a1039d..7271514 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -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)));