summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-02-25 11:15:22 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-02-25 11:15:22 +0000
commitc68de3a262fe58127c2dff6f046cc825509887d2 (patch)
tree8f6648c62770fa3ed908e73bbda0d30bdbc7079e
parent078f08b81a6e4e1b840260d19fe399fbf39ef38c (diff)
downloadcygnal-c68de3a262fe58127c2dff6f046cc825509887d2.tar.gz
cygnal-c68de3a262fe58127c2dff6f046cc825509887d2.tar.bz2
cygnal-c68de3a262fe58127c2dff6f046cc825509887d2.zip
* mmap.cc (class mmap_record): Declare new map_pages method with
address parameter. (mmap_record::map_pages): New method with address parameter. (mmap64): Evaluate access mode before checking if already existing mapping can be used. Only use existing mapping if requested access mode matches the one in the existing mapping. Add check for existing mapping for MAP_FIXED case.
-rw-r--r--winsup/cygwin/ChangeLog11
-rw-r--r--winsup/cygwin/mmap.cc110
2 files changed, 104 insertions, 17 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 076b0ea31..5079dac1a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,14 @@
+2005-02-25 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (class mmap_record): Declare new map_pages method with
+ address parameter.
+ (mmap_record::map_pages): New method with address parameter.
+ (mmap64): Evaluate access mode before checking if already existing
+ mapping can be used.
+ Only use existing mapping if requested access mode matches the one
+ in the existing mapping.
+ Add check for existing mapping for MAP_FIXED case.
+
2005-02-23 Corinna Vinschen <corinna@vinschen.de>
* localtime.cc: Implement setting __tzrule's offset member using
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index d3c4fbefa..068413bb3 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -93,6 +93,7 @@ class mmap_record
DWORD find_unused_pages (DWORD pages);
_off64_t map_pages (_off64_t off, DWORD len);
+ bool map_pages (caddr_t addr, DWORD len);
bool unmap_pages (caddr_t addr, DWORD len);
int access (caddr_t address);
@@ -235,6 +236,45 @@ mmap_record::map_pages (_off64_t off, DWORD len)
}
bool
+mmap_record::map_pages (caddr_t addr, DWORD len)
+{
+ debug_printf ("map_pages (addr=%x, len=%u)", addr, len);
+ DWORD prot, old_prot;
+ DWORD off = addr - base_address_;
+ off /= getpagesize ();
+ len = PAGE_CNT (len);
+ /* First check if the area is unused right now. */
+ for (DWORD l = 0; l < len; ++l)
+ if (MAP_ISSET (off + l))
+ {
+ set_errno (EINVAL);
+ return false;
+ }
+ switch (access_mode_)
+ {
+ case FILE_MAP_WRITE:
+ prot = PAGE_READWRITE;
+ break;
+ case FILE_MAP_READ:
+ prot = PAGE_READONLY;
+ break;
+ default:
+ prot = PAGE_WRITECOPY;
+ break;
+ }
+ if (wincap.virtual_protect_works_on_shared_pages ()
+ && !VirtualProtect (base_address_ + off * getpagesize (),
+ len * getpagesize (), prot, &old_prot))
+ {
+ __seterrno ();
+ return false;
+ }
+ for (; len-- > 0; ++off)
+ MAP_SET (off);
+ return true;
+}
+
+bool
mmap_record::unmap_pages (caddr_t addr, DWORD len)
{
DWORD old_prot;
@@ -536,6 +576,21 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
fh = &fh_paging_file;
}
+ DWORD access = (prot & PROT_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ;
+ /* copy-on-write doesn't work at all on 9x using anonymous maps.
+ Workaround: Anonymous mappings always use normal READ or WRITE
+ access and don't use named file mapping.
+ copy-on-write doesn't also work properly on 9x with real files.
+ While the changes are not propagated to the file, they are
+ visible to other processes sharing the same file mapping object.
+ Workaround: Don't use named file mapping. That should work since
+ sharing file mappings only works reliable using named
+ file mapping on 9x.
+ */
+ if ((flags & MAP_PRIVATE)
+ && (wincap.has_working_copy_on_write () || fd != -1))
+ access = FILE_MAP_COPY;
+
list *map_list = mmapped_areas->get_list_by_fd (fd);
/* First check if this mapping matches into the chunk of another
@@ -544,12 +599,14 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED))
{
mmap_record *rec;
- if ((rec = map_list->search_record (off, len)) != NULL)
+ if ((rec = map_list->search_record (off, len)) != NULL
+ && rec->get_access () == access)
{
if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
{
syscall_printf ("-1 = mmap()");
- ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, "mmap");
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK,
+ "mmap");
return MAP_FAILED;
}
caddr_t ret = rec->get_address () + off;
@@ -558,21 +615,40 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
return ret;
}
}
-
- DWORD access = (prot & PROT_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ;
- /* copy-on-write doesn't work at all on 9x using anonymous maps.
- Workaround: Anonymous mappings always use normal READ or WRITE
- access and don't use named file mapping.
- copy-on-write doesn't also work properly on 9x with real files.
- While the changes are not propagated to the file, they are
- visible to other processes sharing the same file mapping object.
- Workaround: Don't use named file mapping. That should work since
- sharing file mappings only works reliable using named
- file mapping on 9x.
- */
- if ((flags & MAP_PRIVATE)
- && (wincap.has_working_copy_on_write () || fd != -1))
- access = FILE_MAP_COPY;
+ if (map_list && fd == -1 && off == 0 && (flags & MAP_FIXED))
+ {
+ caddr_t u_addr;
+ DWORD u_len;
+ long record_idx = -1;
+ if ((record_idx = map_list->search_record ((caddr_t)addr, len, u_addr,
+ u_len, record_idx)) >= 0)
+ {
+ mmap_record *rec = map_list->get_record (record_idx);
+ if (u_addr > (caddr_t)addr || u_addr + len < (caddr_t)addr + len
+ || rec->get_access () != access)
+ {
+ /* Partial match only, or access mode doesn't match. */
+ /* FIXME: Handle partial mappings gracefully if adjacent
+ memory is available. */
+ set_errno (EINVAL);
+ syscall_printf ("-1 = mmap()");
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
+ "mmap");
+ return MAP_FAILED;
+ }
+ if (!rec->map_pages ((caddr_t)addr, len))
+ {
+ syscall_printf ("-1 = mmap()");
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
+ "mmap");
+ return MAP_FAILED;
+ }
+ caddr_t ret = (caddr_t)addr;
+ syscall_printf ("%x = mmap() succeeded", ret);
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
+ return ret;
+ }
+ }
caddr_t base = (caddr_t)addr;
/* This shifts the base address to the next lower 64K boundary.