* mmap.cc (mmap_record::alloc_map): De-inline. Add offset and length

parameter.  Only protect pages actually unused currently.  Do job
	of map_map() when initializing a map.
	(mmap_record::map_map): Reduce functionality for the reuse case
	of private anonymous mapping.
	(mmap_record::fixup_map): Format change.
	(list::add_record): Add offset and length parameter to call
	mmap_record::alloc_map() correctly.
	(mmap64): Rename `l' variable to `map_list'.  Accomodate above changes.
	(munmap): Rename `l' variable to `map_list'.
	(msync): Ditto.
	(fhandler_disk_file::mmap): Streamline code.
	(mprotect): Ditto.
	(fixup_mmaps_after_fork): Rename `l' variable to `map_list'.
This commit is contained in:
Corinna Vinschen 2003-02-07 20:57:30 +00:00
parent 49b84ce441
commit 4136fdb16b
2 changed files with 121 additions and 104 deletions

View File

@ -1,3 +1,20 @@
2003-02-07 Corinna Vinschen <corinna@vinschen.de>
* mmap.cc (mmap_record::alloc_map): De-inline. Add offset and length
parameter. Only protect pages actually unused currently. Do job
of map_map() when initializing a map.
(mmap_record::map_map): Reduce functionality for the reuse case
of private anonymous mapping.
(mmap_record::fixup_map): Format change.
(list::add_record): Add offset and length parameter to call
mmap_record::alloc_map() correctly.
(mmap64): Rename `l' variable to `map_list'. Accomodate above changes.
(munmap): Rename `l' variable to `map_list'.
(msync): Ditto.
(fhandler_disk_file::mmap): Streamline code.
(mprotect): Ditto.
(fixup_mmaps_after_fork): Rename `l' variable to `map_list'.
2003-02-07 Vaclav Haisman <V.Haisman@sh.cvut.cz>
Christopher Faylor <cgf@redhat.com>

View File

@ -76,20 +76,7 @@ class mmap_record
DWORD get_size () const { return size_to_map_; }
caddr_t get_address () const { return base_address_; }
DWORD *get_map () const { return map_map_; }
void alloc_map ()
{
/* Allocate one bit per page */
map_map_ = (DWORD *) calloc (MAPSIZE (PAGE_CNT (size_to_map_)),
sizeof (DWORD));
if (wincap.virtual_protect_works_on_shared_pages ())
{
DWORD old_prot;
if (!VirtualProtect (base_address_, size_to_map_,
PAGE_NOACCESS, &old_prot))
syscall_printf ("-1 = alloc_map (): %E");
}
}
void alloc_map (__off64_t off, DWORD len);
void free_map () { if (map_map_) free (map_map_); }
DWORD find_empty (DWORD pages);
@ -123,9 +110,41 @@ mmap_record::find_empty (DWORD pages)
return (DWORD)-1;
}
void
mmap_record::alloc_map (__off64_t off, DWORD len)
{
/* Allocate one bit per page */
map_map_ = (DWORD *) calloc (MAPSIZE (PAGE_CNT (size_to_map_)),
sizeof (DWORD));
if (wincap.virtual_protect_works_on_shared_pages ())
{
DWORD old_prot;
off -= offset_;
len = PAGE_CNT (len) * getpagesize ();
if (off > 0 &&
!VirtualProtect (base_address_, off, PAGE_NOACCESS, &old_prot))
syscall_printf ("VirtualProtect(%x,%d) failed: %E", base_address_, off);
if (off + len < size_to_map_
&& !VirtualProtect (base_address_ + off + len,
size_to_map_ - len - off,
PAGE_NOACCESS, &old_prot))
syscall_printf ("VirtualProtect(%x,%d) failed: %E",
base_address_ + off + len, size_to_map_ - len - off);
off /= getpagesize ();
len /= getpagesize ();
while (len-- > 0)
MAP_SET (off + len);
}
}
__off64_t
mmap_record::map_map (__off64_t off, DWORD len)
{
/* Used ONLY if this mapping matches into the chunk of another already
performed mapping in a special case of MAP_ANON|MAP_PRIVATE.
Otherwise it's job is now done by alloc_map(). */
DWORD prot, old_prot;
switch (access_mode_)
{
@ -142,38 +161,20 @@ mmap_record::map_map (__off64_t off, DWORD len)
debug_printf ("map_map (fd=%d, off=%D, len=%d)", fdesc_, off, len);
len = PAGE_CNT (len);
if (fdesc_ == -1 && !off)
{
off = find_empty (len);
if (off != (DWORD)-1)
{
if (wincap.virtual_protect_works_on_shared_pages ()
&& !VirtualProtect (base_address_ + off * getpagesize (),
len * getpagesize (), prot, &old_prot))
{
__seterrno ();
return (__off64_t)-1;
}
while (len-- > 0)
MAP_SET (off + len);
return off * getpagesize ();
}
return 0L;
}
off -= offset_;
DWORD start = off / getpagesize ();
if ((off = find_empty (len)) == (DWORD)-1)
return 0L;
if (wincap.virtual_protect_works_on_shared_pages ()
&& !VirtualProtect (base_address_ + start * getpagesize (),
&& !VirtualProtect (base_address_ + off * getpagesize (),
len * getpagesize (), prot, &old_prot))
{
__seterrno ();
return (__off64_t)-1;
}
for (; len-- > 0; ++start)
MAP_SET (start);
return off;
while (len-- > 0)
MAP_SET (off + len);
return off * getpagesize ();
}
BOOL
@ -219,10 +220,8 @@ mmap_record::fixup_map ()
}
for (DWORD off = PAGE_CNT (size_to_map_); off > 0; --off)
VirtualProtect (base_address_ + off * getpagesize (),
getpagesize (),
MAP_ISSET (off - 1) ? prot : PAGE_NOACCESS,
&old_prot);
VirtualProtect (base_address_ + off * getpagesize (), getpagesize (),
MAP_ISSET (off - 1) ? prot : PAGE_NOACCESS, &old_prot);
}
int
@ -268,7 +267,7 @@ public:
DWORD hash;
list ();
~list ();
mmap_record *add_record (mmap_record r);
mmap_record *add_record (mmap_record r, __off64_t off, DWORD len);
void erase (int i);
void erase ();
mmap_record *match (__off64_t off, DWORD len);
@ -289,7 +288,7 @@ list::~list ()
}
mmap_record *
list::add_record (mmap_record r)
list::add_record (mmap_record r, __off64_t off, DWORD len)
{
if (nrecs == maxrecs)
{
@ -297,7 +296,7 @@ list::add_record (mmap_record r)
recs = (mmap_record *) realloc (recs, maxrecs * sizeof (mmap_record));
}
recs[nrecs] = r;
recs[nrecs].alloc_map ();
recs[nrecs].alloc_map (off, len);
return recs + nrecs++;
}
@ -416,7 +415,7 @@ map::erase (int i)
* Code to keep a record of all mmap'ed areas in a process.
* Needed to duplicate tham in a child of fork().
* mmap_record classes are kept in an STL list in an STL map, keyed
* by file descriptor. This is *NOT* duplicated accross a fork(), it
* by file descriptor. This is *NOT* duplicated across a fork(), it
* needs to be specially handled by the fork code.
*/
@ -505,15 +504,15 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, __off64_t off)
fh = &fh_paging_file;
}
list *l = 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
already performed mapping. Only valid for MAP_ANON in a special
case of MAP_PRIVATE. */
if (l && fd == -1 && off == 0 && !(flags & MAP_FIXED))
if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED))
{
mmap_record *rec;
if ((rec = l->match (off, len)) != NULL)
if ((rec = map_list->match (off, len)) != NULL)
{
if ((off = rec->map_map (off, len)) == (__off64_t)-1)
{
@ -561,11 +560,11 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, __off64_t off)
/* Get list of mmapped areas for this fd, create a new one if
one does not exist yet.
*/
if (l == 0)
if (!map_list)
{
/* Create a new one */
l = new list;
if (l == 0)
map_list = new list;
if (!map_list)
{
fh->munmap (h, base, gran_len);
set_errno (ENOMEM);
@ -573,19 +572,11 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, __off64_t off)
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
return MAP_FAILED;
}
l = mmapped_areas->add_list (l, fd);
map_list = mmapped_areas->add_list (map_list, fd);
}
/* Insert into the list */
mmap_record *rec = l->add_record (mmap_rec);
if ((off = rec->map_map (off, len)) == (__off64_t)-1)
{
fh->munmap (h, base, gran_len);
l->erase ();
syscall_printf ("-1 = mmap()");
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
return MAP_FAILED;
}
mmap_record *rec = map_list->add_record (mmap_rec, off, len);
caddr_t ret = rec->get_address () + off;
syscall_printf ("%x = mmap() succeeded", ret);
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
@ -631,13 +622,13 @@ munmap (caddr_t addr, size_t len)
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
list *l = mmapped_areas->lists[it];
if (l)
list *map_list = mmapped_areas->lists[it];
if (map_list)
{
long li = -1;
if ((li = l->match(addr, len, li)) >= 0)
if ((li = map_list->match(addr, len, li)) >= 0)
{
mmap_record *rec = l->recs + li;
mmap_record *rec = map_list->recs + li;
if (rec->unmap_map (addr, len))
{
fhandler_base *fh = rec->alloc_fh ();
@ -645,7 +636,7 @@ munmap (caddr_t addr, size_t len)
rec->free_fh (fh);
/* Delete the entry. */
l->erase (li);
map_list->erase (li);
}
syscall_printf ("0 = munmap(): %x", addr);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
@ -694,12 +685,12 @@ msync (caddr_t addr, size_t len, int flags)
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
list *l = mmapped_areas->lists[it];
if (l != 0)
list *map_list = mmapped_areas->lists[it];
if (map_list != 0)
{
for (int li = 0; li < l->nrecs; ++li)
for (int li = 0; li < map_list->nrecs; ++li)
{
mmap_record *rec = l->recs + li;
mmap_record *rec = map_list->recs + li;
if (rec->access (addr))
{
/* Check whole area given by len. */
@ -715,7 +706,8 @@ msync (caddr_t addr, size_t len, int flags)
else
syscall_printf ("0 = msync()");
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "msync");
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK,
"msync");
return 0;
}
}
@ -780,12 +772,18 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, DWORD access,
{
DWORD protect;
if (access & FILE_MAP_COPY)
protect = PAGE_WRITECOPY;
else if (access & FILE_MAP_WRITE)
protect = PAGE_READWRITE;
else
protect = PAGE_READONLY;
switch (access)
{
case FILE_MAP_WRITE:
protect = PAGE_READWRITE;
break;
case FILE_MAP_READ:
protect = PAGE_READONLY;
break;
default:
protect = PAGE_WRITECOPY;
break;
}
HANDLE h;
@ -896,29 +894,31 @@ mprotect (caddr_t addr, size_t len, int prot)
return 0;
}
if (prot == PROT_NONE)
new_prot = PAGE_NOACCESS;
else
switch (prot)
{
switch (prot)
{
case PROT_READ | PROT_WRITE | PROT_EXEC:
new_prot = PAGE_EXECUTE_READWRITE;
break;
case PROT_READ | PROT_WRITE:
new_prot = PAGE_READWRITE;
break;
case PROT_READ | PROT_EXEC:
new_prot = PAGE_EXECUTE_READ;
break;
case PROT_READ:
new_prot = PAGE_READONLY;
break;
default:
syscall_printf ("-1 = mprotect (): invalid prot value");
set_errno (EINVAL);
return -1;
}
case PROT_READ | PROT_WRITE | PROT_EXEC:
case PROT_WRITE | PROT_EXEC:
new_prot = PAGE_EXECUTE_READWRITE;
break;
case PROT_READ | PROT_WRITE:
case PROT_WRITE:
new_prot = PAGE_READWRITE;
break;
case PROT_READ | PROT_EXEC:
new_prot = PAGE_EXECUTE_READ;
break;
case PROT_READ:
new_prot = PAGE_READONLY;
case PROT_EXEC:
new_prot = PAGE_EXECUTE;
break;
case PROT_NONE:
new_prot = PAGE_NOACCESS;
break;
default:
syscall_printf ("-1 = mprotect (): invalid prot value");
set_errno (EINVAL);
return -1;
}
if (VirtualProtect (addr, len, new_prot, &old_prot) == 0)
@ -954,13 +954,13 @@ fixup_mmaps_after_fork (HANDLE parent)
/* Iterate through the map */
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
list *l = mmapped_areas->lists[it];
if (l)
list *map_list = mmapped_areas->lists[it];
if (map_list)
{
int li;
for (li = 0; li < l->nrecs; ++li)
for (li = 0; li < map_list->nrecs; ++li)
{
mmap_record *rec = l->recs + li;
mmap_record *rec = map_list->recs + li;
debug_printf ("fd %d, h %x, access %x, offset %d, size %d, address %p",
rec->get_fd (), rec->get_handle (), rec->get_access (),