aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-07-19 11:11:14 +0000
committerCorinna Vinschen <corinna@vinschen.de>2006-07-19 11:11:14 +0000
commitc2d7650c68ad01823f8b7f5febec5708fc2ac0d6 (patch)
tree7a35a3c55b81d1183beb5007cc8a32f22d7d51d6
parent6902793ada2e1bef45deed519c3fb73e47410851 (diff)
downloadnewlib-c2d7650c68ad01823f8b7f5febec5708fc2ac0d6.zip
newlib-c2d7650c68ad01823f8b7f5febec5708fc2ac0d6.tar.gz
newlib-c2d7650c68ad01823f8b7f5febec5708fc2ac0d6.tar.bz2
* Merge HEAD into cv-branch.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/mmap.cc94
-rw-r--r--winsup/cygwin/path.cc3
3 files changed, 49 insertions, 57 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 8dba361..2ec1cab 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,12 @@
+2006-07-19 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (msync): Disable rounding up len. Fix bug in access check
+ loop.
+
+2006-07-19 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (symlink_worker): Return EEXIST if newpath exists.
+
2006-07-18 Christopher Faylor <cgf@timesys.com>
* tty.cc (tty_list::terminate): Don't enter the busy loop if we don't
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index a46c4a4..9796651 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -900,64 +900,44 @@ map::del_list (unsigned i)
}
/* 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 mmap page addresses
- to Windows system calls. In that case, it should be called only after
- a system call indicates that the application buffer passed had an
- invalid virtual address to avoid any performance impact in non-noreserve
- cases.
+ violation has happened. We have two cases to check here.
- Check if the address range is all within noreserve mmap regions. If so,
- call VirtualAlloc to commit the pages and return MMAP_NORESERVE_COMMITED
- on success. If the page has __PROT_ATTACH (SUSv3 memory protection
- extension), or if VirutalAlloc fails, return MMAP_RAISE_SIGBUS.
- Otherwise, return MMAP_NONE if the address range is not covered by an
- attached or noreserve map.
-
- On MAP_NORESERVE_COMMITED, the exeception handler should return 0 to
- allow the application to retry the memory access, or the calling Cygwin
- function should retry the Windows system call. */
-mmap_region_status
-mmap_is_attached_or_noreserve (void *addr, size_t len)
+ 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 = mmapped_areas.get_list_by_fd (-1);
-
- size_t pagesize = getpagesize ();
- caddr_t start_addr = (caddr_t) rounddown ((uintptr_t) addr, pagesize);
- len += ((caddr_t) addr - start_addr);
- len = roundup2 (len, pagesize);
-
- if (map_list == NULL)
- return MMAP_NONE;
-
- while (len > 0)
- {
- caddr_t u_addr;
- DWORD u_len;
- long record_idx = map_list->search_record (start_addr, len,
- u_addr, u_len, -1);
- if (record_idx < 0)
- return MMAP_NONE;
-
- mmap_record *rec = map_list->get_record (record_idx);
- if (rec->attached ())
- return MMAP_RAISE_SIGBUS;
- if (!rec->noreserve ())
- return MMAP_NONE;
-
- size_t commit_len = u_len - (start_addr - u_addr);
- if (commit_len > len)
- commit_len = len;
-
- if (!VirtualAlloc (start_addr, commit_len, MEM_COMMIT,
- rec->gen_protect ()))
- return MMAP_RAISE_SIGBUS;
-
- start_addr += commit_len;
- len -= commit_len;
- }
+ list *map_list;
+ long record_idx;
+ caddr_t u_addr;
+ DWORD u_len;
+ DWORD pagesize = getsystempagesize ();
- return MMAP_NORESERVE_COMMITED;
+ addr = rounddown (addr, pagesize);
+ if (!(map_list = mmapped_areas.get_list_by_fd (-1)))
+ return 0;
+ if ((record_idx = map_list->search_record ((caddr_t)addr, pagesize,
+ u_addr, u_len, -1)) < 0)
+ 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
@@ -1372,7 +1352,9 @@ msync (void *addr, size_t len, int flags)
set_errno (EINVAL);
goto out;
}
+#if 0 /* If I only knew why I did that... */
len = roundup2 (len, pagesize);
+#endif
/* Iterate through the map, looking for the mmapped area.
Error if not found. */
@@ -1388,7 +1370,7 @@ msync (void *addr, size_t len, int flags)
if (rec->access ((caddr_t)addr))
{
/* Check whole area given by len. */
- for (DWORD i = getpagesize (); i < len; ++i)
+ for (DWORD i = getpagesize (); i < len; i += getpagesize ())
if (!rec->access ((caddr_t)addr + i))
{
set_errno (ENOMEM);
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 1166916..f857f16 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2757,7 +2757,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
syscall_printf ("symlink (%s, %s)", oldpath, win32_path.get_win32 ());
- if (win32_path.is_auto_device ())
+ if ((!isdevice && win32_path.exists ())
+ || win32_path.is_auto_device ())
{
set_errno (EEXIST);
goto done;