* 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.
This commit is contained in:
Corinna Vinschen 2005-02-25 21:23:15 +00:00
parent 99e281eb19
commit 6d11044c63
5 changed files with 176 additions and 68 deletions

View File

@ -1,3 +1,33 @@
2005-02-25 Corinna Vinschen <corinna@vinschen.de>
* 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 <corinna@vinschen.de>
* mmap.cc (mmap64): Handle anonymous MAP_FIXED request on

View File

@ -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 ();
} ;

View File

@ -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;

View File

@ -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))
/* A bit of memory munging on 9x. */
if (map_list && fd == -1 && wincap.share_mmaps_only_by_name ())
{
mmap_record *rec;
if ((rec = map_list->search_record (off, len)) != NULL
&& rec->get_access () == access)
/* 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))
{
if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
mmap_record *rec;
if ((rec = map_list->search_record (off, len)) != NULL
&& rec->get_access () == access)
{
syscall_printf ("-1 = mmap()");
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK,
"mmap");
return MAP_FAILED;
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;
}
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))
{
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)
if ((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)
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)
{
/* 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()");
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;
}
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;
}
}
@ -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 ());

View File

@ -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