From 6d11044c633bc7aca545c5409327ef023646205b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 25 Feb 2005 21:23:15 +0000 Subject: * fhandler.h (class fhandler_base): Declare fixup_mmap_after_fork with additional flags parameter. Change offset parameter to _off64_t. (class fhandler_disk_file): Ditto. (class fhandler_dev_mem): Ditto. * fhandler_mem.cc (fhandler_dev_mem::fixup_mmap_after_fork): Accomodate new parameters. * mmap.cc: Include ntdll.h. (class mmap_record): Add flags member. (mmap_record::mmap_record): Add flags parameter. (mmap_record::get_flags): New method. (class map): Add next_anon_addr member to store next anonymous mapping address suggestion. (map::get_next_anon_addr): New method. (map::set_next_anon_addr): New method. (mmap64): Don't align offset and length to granularity in case of MAP_ANONYMOUS on NT. Check for already existing mapping only on 9x. Call mmap_record::mmap_record with additional flags argument. (fhandler_base::fixup_mmap_after_fork): Accomodate new parameters. (fhandler_disk_file::mmap): Use NtMapViewOfSection with AT_ROUND_TO_PAGE flag for anonymous mappings on NT. If addr is NULL, try to map adjacent to previous mapping. (fhandler_disk_file::fixup_mmap_after_fork): Add flags argument. Change offset parameter to _off64_t. Use NtMapViewOfSection to re-create anonymous mappings on NT. (fixup_mmaps_after_fork): Accomodate new parameters when calling fhandler's fixup_mmaps_after_fork function. * ntdll.h (AT_ROUND_TO_PAGE): New define. --- winsup/cygwin/ChangeLog | 30 +++++++ winsup/cygwin/fhandler.h | 13 +-- winsup/cygwin/fhandler_mem.cc | 5 +- winsup/cygwin/mmap.cc | 194 +++++++++++++++++++++++++++++------------- winsup/cygwin/ntdll.h | 2 + 5 files changed, 176 insertions(+), 68 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 003a185ba..9a5de4d70 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,33 @@ +2005-02-25 Corinna Vinschen + + * fhandler.h (class fhandler_base): Declare fixup_mmap_after_fork + with additional flags parameter. Change offset parameter to _off64_t. + (class fhandler_disk_file): Ditto. + (class fhandler_dev_mem): Ditto. + * fhandler_mem.cc (fhandler_dev_mem::fixup_mmap_after_fork): + Accomodate new parameters. + * mmap.cc: Include ntdll.h. + (class mmap_record): Add flags member. + (mmap_record::mmap_record): Add flags parameter. + (mmap_record::get_flags): New method. + (class map): Add next_anon_addr member to store next anonymous mapping + address suggestion. + (map::get_next_anon_addr): New method. + (map::set_next_anon_addr): New method. + (mmap64): Don't align offset and length to granularity in case of + MAP_ANONYMOUS on NT. Check for already existing mapping only on 9x. + Call mmap_record::mmap_record with additional flags argument. + (fhandler_base::fixup_mmap_after_fork): Accomodate new parameters. + (fhandler_disk_file::mmap): Use NtMapViewOfSection with + AT_ROUND_TO_PAGE flag for anonymous mappings on NT. If addr is NULL, + try to map adjacent to previous mapping. + (fhandler_disk_file::fixup_mmap_after_fork): Add flags argument. + Change offset parameter to _off64_t. Use NtMapViewOfSection to + re-create anonymous mappings on NT. + (fixup_mmaps_after_fork): Accomodate new parameters when calling + fhandler's fixup_mmaps_after_fork function. + * ntdll.h (AT_ROUND_TO_PAGE): New define. + 2005-02-25 Corinna Vinschen * mmap.cc (mmap64): Handle anonymous MAP_FIXED request on diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index d3250d1b2..2d9aa5f7f 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -285,8 +285,9 @@ class fhandler_base int flags, _off64_t off); virtual int munmap (HANDLE h, caddr_t addr, size_t len); virtual int msync (HANDLE h, caddr_t addr, size_t len, int flags); - virtual bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address); + virtual bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, + void *address); void *operator new (size_t, void *p) {return p;} @@ -633,8 +634,8 @@ class fhandler_disk_file: public fhandler_base HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, _off64_t off); int munmap (HANDLE h, caddr_t addr, size_t len); int msync (HANDLE h, caddr_t addr, size_t len, int flags); - bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address); + bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, void *address); DIR *opendir (); struct dirent *readdir (DIR *); _off64_t telldir (DIR *); @@ -1055,8 +1056,8 @@ class fhandler_dev_mem: public fhandler_base HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, _off64_t off); int munmap (HANDLE h, caddr_t addr, size_t len); int msync (HANDLE h, caddr_t addr, size_t len, int flags); - bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address); + bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, void *address); void dump (); } ; diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index 68532c6dd..4c873d758 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -361,8 +361,9 @@ fhandler_dev_mem::msync (HANDLE h, caddr_t addr, size_t len, int flags) } bool -fhandler_dev_mem::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address) +fhandler_dev_mem::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, + void *address) { DWORD ret; PHYSICAL_ADDRESS phys; diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 1a8f15338..36db16ce6 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -22,6 +22,7 @@ details. */ #include "cygheap.h" #include "pinfo.h" #include "sys/cygwin.h" +#include "ntdll.h" #define PAGE_CNT(bytes) howmany((bytes),getpagesize()) @@ -58,6 +59,7 @@ class mmap_record int fdesc_; HANDLE mapping_handle_; DWORD access_mode_; + int flags_; _off64_t offset_; DWORD size_to_map_; caddr_t base_address_; @@ -65,10 +67,12 @@ class mmap_record device dev; public: - mmap_record (int fd, HANDLE h, DWORD ac, _off64_t o, DWORD s, caddr_t b) : + mmap_record (int fd, HANDLE h, DWORD ac, int f, _off64_t o, DWORD s, + caddr_t b) : fdesc_ (fd), mapping_handle_ (h), access_mode_ (ac), + flags_ (f), offset_ (o), size_to_map_ (s), base_address_ (b), @@ -83,6 +87,7 @@ class mmap_record HANDLE get_handle () const { return mapping_handle_; } device& get_device () { return dev; } DWORD get_access () const { return access_mode_; } + DWORD get_flags () const { return flags_; } _off64_t get_offset () const { return offset_; } DWORD get_size () const { return size_to_map_; } caddr_t get_address () const { return base_address_; } @@ -128,12 +133,15 @@ class map private: list *lists; int nlists, maxlists; + caddr_t next_anon_addr; public: list *get_list (int i) { return i >= nlists ? NULL : lists + i; } list *get_list_by_fd (int fd); list *add_list (int fd); void del_list (int i); + caddr_t get_next_anon_addr () { return next_anon_addr; } + void set_next_anon_addr (caddr_t addr) { next_anon_addr = addr; } }; /* This is the global map structure pointer. It's allocated once on the @@ -530,13 +538,21 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off) if (flags & MAP_ANONYMOUS) fd = -1; - /* If MAP_FIXED is requested on a non-granularity boundary, change request - so that this looks like a request with offset addr % granularity. */ - if (fd == -1 && (flags & MAP_FIXED) && ((DWORD)addr % granularity) && !off) + /* 9x only: If MAP_FIXED is requested on a non-granularity boundary, + change request so that this looks like a request with offset + addr % granularity. */ + if (wincap.share_mmaps_only_by_name () && fd == -1 && (flags & MAP_FIXED) + && ((DWORD)addr % granularity) && !off) off = (DWORD)addr % granularity; - /* Map always in multipliers of `granularity'-sized chunks. */ - _off64_t gran_off = off & ~(granularity - 1); - DWORD gran_len = howmany (off + len, granularity) * granularity - gran_off; + /* Map always in multipliers of `granularity'-sized chunks. + Not necessary for anonymous maps on NT. */ + _off64_t gran_off = off; + DWORD gran_len = len; + if (wincap.share_mmaps_only_by_name () || fd != -1) + { + gran_off = off & ~(granularity - 1); + gran_len = howmany (off + len, granularity) * granularity - gran_off; + } fhandler_base *fh; @@ -571,8 +587,11 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off) gran_len = fsiz; } else if (fh->get_device () == FH_ZERO) - /* mmap /dev/zero is like MAP_ANONYMOUS. */ - fd = -1; + { + /* mmap /dev/zero is like MAP_ANONYMOUS. */ + fd = -1; + flags |= MAP_ANONYMOUS; + } } if (fd == -1) { @@ -597,60 +616,67 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off) list *map_list = mmapped_areas->get_list_by_fd (fd); - /* First check if this mapping matches into the chunk of another - already performed mapping. Only valid for MAP_ANON in a special - case of MAP_PRIVATE. */ - if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED)) - { - mmap_record *rec; - 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"); - return MAP_FAILED; - } - caddr_t ret = rec->get_address () + off; - syscall_printf ("%x = mmap() succeeded", ret); - ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); - return ret; - } - } - if (map_list && fd == -1 && (flags & MAP_FIXED)) + /* A bit of memory munging on 9x. */ + if (map_list && fd == -1 && wincap.share_mmaps_only_by_name ()) { - 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) + /* First check if this mapping matches into the chunk of another + already performed mapping. Only valid for MAP_ANON in a special + case of MAP_PRIVATE. */ + if (off == 0 && !(flags & MAP_FIXED)) { - 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) + mmap_record *rec; + if ((rec = map_list->search_record (off, len)) != NULL + && 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()"); + if ((off = rec->map_pages (off, len)) == (_off64_t)-1) + { + syscall_printf ("-1 = mmap()"); + ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, + "mmap"); + return MAP_FAILED; + } + caddr_t ret = rec->get_address () + off; + syscall_printf ("%x = mmap() succeeded", ret); ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); - return MAP_FAILED; + return ret; } - if (!rec->map_pages ((caddr_t)addr, len)) + } + if ((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) { - syscall_printf ("-1 = mmap()"); + 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 MAP_FAILED; + return ret; } - caddr_t ret = (caddr_t)addr; - syscall_printf ("%x = mmap() succeeded", ret); - ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); - return ret; } } @@ -672,7 +698,7 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off) Now it's time for bookkeeping stuff. */ if (fd == -1) gran_len = PAGE_CNT (gran_len) * getpagesize (); - mmap_record mmap_rec (fd, h, access, gran_off, gran_len, base); + mmap_record mmap_rec (fd, h, access, flags, gran_off, gran_len, base); /* Get list of mmapped areas for this fd, create a new one if one does not exist yet. @@ -959,8 +985,9 @@ fhandler_base::msync (HANDLE h, caddr_t addr, size_t len, int flags) } bool -fhandler_base::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address) +fhandler_base::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, + void *address) { set_errno (ENODEV); return -1; @@ -1022,7 +1049,25 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, DWORD access, void *base = NULL; /* If a non-zero address is given, try mapping using the given address first. If it fails and flags is not MAP_FIXED, try again with NULL address. */ - if (*addr) + if (!wincap.share_mmaps_only_by_name () + && get_handle () == INVALID_HANDLE_VALUE) + { + PHYSICAL_ADDRESS phys; + phys.QuadPart = (ULONGLONG) off; + ULONG ulen = len; + base = *addr ?: (void *) mmapped_areas->get_next_anon_addr (); + NTSTATUS ret = NtMapViewOfSection (h, INVALID_HANDLE_VALUE, &base, 0L, + ulen, &phys, &ulen, ViewShare, + base ? AT_ROUND_TO_PAGE : 0, protect); + if (ret != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + base = NULL; + } + else + mmapped_areas->set_next_anon_addr ((caddr_t) base + len); + } + else if (*addr) base = MapViewOfFileEx (h, access, high, low, len, *addr); if (!base && !(flags & MAP_FIXED)) base = MapViewOfFileEx (h, access, high, low, len, NULL); @@ -1068,11 +1113,39 @@ fhandler_disk_file::msync (HANDLE h, caddr_t addr, size_t len, int flags) } bool -fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, - DWORD size, void *address) +fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags, + _off64_t offset, DWORD size, + void *address) { /* Re-create the MapViewOfFileEx call */ - void *base = MapViewOfFileEx (h, access, 0, offset, size, address); + void *base; + if (!wincap.share_mmaps_only_by_name () && (flags & MAP_ANONYMOUS)) + { + PHYSICAL_ADDRESS phys; + phys.QuadPart = (ULONGLONG) offset; + ULONG ulen = size; + base = address; + DWORD protect; + switch (access) + { + case FILE_MAP_WRITE: + protect = PAGE_READWRITE; + break; + case FILE_MAP_READ: + protect = PAGE_READONLY; + break; + default: + protect = PAGE_WRITECOPY; + break; + } + NTSTATUS ret = NtMapViewOfSection (h, INVALID_HANDLE_VALUE, &base, 0L, + ulen, &phys, &ulen, ViewShare, + AT_ROUND_TO_PAGE, protect); + if (ret != STATUS_SUCCESS) + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + } + else + base = MapViewOfFileEx (h, access, 0, offset, size, address); if (base != address) { MEMORY_BASIC_INFORMATION m; @@ -1121,6 +1194,7 @@ fixup_mmaps_after_fork (HANDLE parent) fhandler_base *fh = rec->alloc_fh (); bool ret = fh->fixup_mmap_after_fork (rec->get_handle (), rec->get_access (), + rec->get_flags (), rec->get_offset (), rec->get_size (), rec->get_address ()); diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 23ce468cd..844a131b5 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -23,6 +23,8 @@ #define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0 #define WSLE_PAGE_SHAREABLE 0x100 +#define AT_ROUND_TO_PAGE 0x40000000 + typedef ULONG KAFFINITY; typedef enum _SYSTEM_INFORMATION_CLASS -- cgit v1.2.3