* 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:
parent
99e281eb19
commit
6d11044c63
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
} ;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ());
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue