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

View File

@ -285,8 +285,9 @@ class fhandler_base
int flags, _off64_t off); int flags, _off64_t off);
virtual int munmap (HANDLE h, caddr_t addr, size_t len); 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 int msync (HANDLE h, caddr_t addr, size_t len, int flags);
virtual bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, virtual bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address); _off64_t offset, DWORD size,
void *address);
void *operator new (size_t, void *p) {return p;} 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); 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 munmap (HANDLE h, caddr_t addr, size_t len);
int msync (HANDLE h, caddr_t addr, size_t len, int flags); int msync (HANDLE h, caddr_t addr, size_t len, int flags);
bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address); _off64_t offset, DWORD size, void *address);
DIR *opendir (); DIR *opendir ();
struct dirent *readdir (DIR *); struct dirent *readdir (DIR *);
_off64_t telldir (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); 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 munmap (HANDLE h, caddr_t addr, size_t len);
int msync (HANDLE h, caddr_t addr, size_t len, int flags); int msync (HANDLE h, caddr_t addr, size_t len, int flags);
bool fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address); _off64_t offset, DWORD size, void *address);
void dump (); void dump ();
} ; } ;

View File

@ -361,8 +361,9 @@ fhandler_dev_mem::msync (HANDLE h, caddr_t addr, size_t len, int flags)
} }
bool bool
fhandler_dev_mem::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, fhandler_dev_mem::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address) _off64_t offset, DWORD size,
void *address)
{ {
DWORD ret; DWORD ret;
PHYSICAL_ADDRESS phys; PHYSICAL_ADDRESS phys;

View File

@ -22,6 +22,7 @@ details. */
#include "cygheap.h" #include "cygheap.h"
#include "pinfo.h" #include "pinfo.h"
#include "sys/cygwin.h" #include "sys/cygwin.h"
#include "ntdll.h"
#define PAGE_CNT(bytes) howmany((bytes),getpagesize()) #define PAGE_CNT(bytes) howmany((bytes),getpagesize())
@ -58,6 +59,7 @@ class mmap_record
int fdesc_; int fdesc_;
HANDLE mapping_handle_; HANDLE mapping_handle_;
DWORD access_mode_; DWORD access_mode_;
int flags_;
_off64_t offset_; _off64_t offset_;
DWORD size_to_map_; DWORD size_to_map_;
caddr_t base_address_; caddr_t base_address_;
@ -65,10 +67,12 @@ class mmap_record
device dev; device dev;
public: 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), fdesc_ (fd),
mapping_handle_ (h), mapping_handle_ (h),
access_mode_ (ac), access_mode_ (ac),
flags_ (f),
offset_ (o), offset_ (o),
size_to_map_ (s), size_to_map_ (s),
base_address_ (b), base_address_ (b),
@ -83,6 +87,7 @@ class mmap_record
HANDLE get_handle () const { return mapping_handle_; } HANDLE get_handle () const { return mapping_handle_; }
device& get_device () { return dev; } device& get_device () { return dev; }
DWORD get_access () const { return access_mode_; } DWORD get_access () const { return access_mode_; }
DWORD get_flags () const { return flags_; }
_off64_t get_offset () const { return offset_; } _off64_t get_offset () const { return offset_; }
DWORD get_size () const { return size_to_map_; } DWORD get_size () const { return size_to_map_; }
caddr_t get_address () const { return base_address_; } caddr_t get_address () const { return base_address_; }
@ -128,12 +133,15 @@ class map
private: private:
list *lists; list *lists;
int nlists, maxlists; int nlists, maxlists;
caddr_t next_anon_addr;
public: public:
list *get_list (int i) { return i >= nlists ? NULL : lists + i; } list *get_list (int i) { return i >= nlists ? NULL : lists + i; }
list *get_list_by_fd (int fd); list *get_list_by_fd (int fd);
list *add_list (int fd); list *add_list (int fd);
void del_list (int i); 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 /* 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) if (flags & MAP_ANONYMOUS)
fd = -1; fd = -1;
/* If MAP_FIXED is requested on a non-granularity boundary, change request /* 9x only: If MAP_FIXED is requested on a non-granularity boundary,
so that this looks like a request with offset addr % granularity. */ change request so that this looks like a request with offset
if (fd == -1 && (flags & MAP_FIXED) && ((DWORD)addr % granularity) && !off) addr % granularity. */
if (wincap.share_mmaps_only_by_name () && fd == -1 && (flags & MAP_FIXED)
&& ((DWORD)addr % granularity) && !off)
off = (DWORD)addr % granularity; off = (DWORD)addr % granularity;
/* Map always in multipliers of `granularity'-sized chunks. */ /* Map always in multipliers of `granularity'-sized chunks.
_off64_t gran_off = off & ~(granularity - 1); Not necessary for anonymous maps on NT. */
DWORD gran_len = howmany (off + len, granularity) * granularity - gran_off; _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; 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; gran_len = fsiz;
} }
else if (fh->get_device () == FH_ZERO) 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) 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); list *map_list = mmapped_areas->get_list_by_fd (fd);
/* First check if this mapping matches into the chunk of another /* A bit of memory munging on 9x. */
already performed mapping. Only valid for MAP_ANON in a special if (map_list && fd == -1 && wincap.share_mmaps_only_by_name ())
case of MAP_PRIVATE. */
if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED))
{ {
mmap_record *rec; /* First check if this mapping matches into the chunk of another
if ((rec = map_list->search_record (off, len)) != NULL already performed mapping. Only valid for MAP_ANON in a special
&& rec->get_access () == access) 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()"); if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, {
"mmap"); syscall_printf ("-1 = mmap()");
return MAP_FAILED; 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 ((flags & MAP_FIXED))
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)
{ {
mmap_record *rec = map_list->get_record (record_idx); caddr_t u_addr;
if (u_addr > (caddr_t)addr || u_addr + len < (caddr_t)addr + len DWORD u_len;
|| rec->get_access () != access) 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. */ mmap_record *rec = map_list->get_record (record_idx);
/* FIXME: Handle partial mappings gracefully if adjacent if (u_addr > (caddr_t)addr || u_addr + len < (caddr_t)addr + len
memory is available. */ || rec->get_access () != access)
set_errno (EINVAL); {
syscall_printf ("-1 = mmap()"); /* 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, ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
"mmap"); "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. */ Now it's time for bookkeeping stuff. */
if (fd == -1) if (fd == -1)
gran_len = PAGE_CNT (gran_len) * getpagesize (); 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 /* Get list of mmapped areas for this fd, create a new one if
one does not exist yet. one does not exist yet.
@ -959,8 +985,9 @@ fhandler_base::msync (HANDLE h, caddr_t addr, size_t len, int flags)
} }
bool bool
fhandler_base::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, fhandler_base::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address) _off64_t offset, DWORD size,
void *address)
{ {
set_errno (ENODEV); set_errno (ENODEV);
return -1; return -1;
@ -1022,7 +1049,25 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, DWORD access,
void *base = NULL; void *base = NULL;
/* If a non-zero address is given, try mapping using the given address first. /* 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 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); base = MapViewOfFileEx (h, access, high, low, len, *addr);
if (!base && !(flags & MAP_FIXED)) if (!base && !(flags & MAP_FIXED))
base = MapViewOfFileEx (h, access, high, low, len, NULL); 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 bool
fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
DWORD size, void *address) _off64_t offset, DWORD size,
void *address)
{ {
/* Re-create the MapViewOfFileEx call */ /* 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) if (base != address)
{ {
MEMORY_BASIC_INFORMATION m; MEMORY_BASIC_INFORMATION m;
@ -1121,6 +1194,7 @@ fixup_mmaps_after_fork (HANDLE parent)
fhandler_base *fh = rec->alloc_fh (); fhandler_base *fh = rec->alloc_fh ();
bool ret = fh->fixup_mmap_after_fork (rec->get_handle (), bool ret = fh->fixup_mmap_after_fork (rec->get_handle (),
rec->get_access (), rec->get_access (),
rec->get_flags (),
rec->get_offset (), rec->get_offset (),
rec->get_size (), rec->get_size (),
rec->get_address ()); rec->get_address ());

View File

@ -23,6 +23,8 @@
#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0 #define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0
#define WSLE_PAGE_SHAREABLE 0x100 #define WSLE_PAGE_SHAREABLE 0x100
#define AT_ROUND_TO_PAGE 0x40000000
typedef ULONG KAFFINITY; typedef ULONG KAFFINITY;
typedef enum _SYSTEM_INFORMATION_CLASS typedef enum _SYSTEM_INFORMATION_CLASS