diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2003-09-04 10:27:51 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2003-09-04 10:27:51 +0000 |
commit | 4544f7f6a2ae3211707994a425fb57dffb4f34fe (patch) | |
tree | b651c64a93133bbb10460e05afa13f1d4c19abe0 /winsup | |
parent | 026dcb34c6d72993b681fc16dee6979355c28ab4 (diff) | |
download | newlib-4544f7f6a2ae3211707994a425fb57dffb4f34fe.zip newlib-4544f7f6a2ae3211707994a425fb57dffb4f34fe.tar.gz newlib-4544f7f6a2ae3211707994a425fb57dffb4f34fe.tar.bz2 |
* mmap.cc: Restructure. Add, remove and rewrite comments throughout
for better readability. Change function names for better
understanding.
(MAP_SET): Accomodate name change from map_map_ to page_map_.
(MAP_CLR): Ditto.
(MAP_ISSET): Ditto.
(mmap_record::page_map_): Rename from page_map_.
(mmap_record::get_map): Remove.
(mmap_record::alloc_page_map): Rename from alloc_map. Return bool
indicating success of cygheap memory allocation.
(mmap_record::free_page_map): Rename from free_map.
(mmap_record::fixup_page_map): Rename from fixup_map.
(mmap_record::find_unused_pages): Rename from find_empty.
(mmap_record::map_pages): Rename from map_map.
(mmap_record::unmap_pages): Rename from unmap_map.
(class list): Make all class members private.
(list::list): Remove.
(list::~list): Remove.
(list::get_fd): New attribute reader.
(list::get_hash): Ditto.
(list::get_record): Ditto.
(list::add_record): Manage all allocation for mmap_records. Check
for failed memory allocation and return NULL if so.
(list::set): New function.
(list::del_record): Rename from erase. Return true if last mmap_record
has been deleted, false otherwise. Check for legal incoming index
value.
(list::erase): Remove erase/0.
(list::search_record): Rename from match.
(map::map): Remove.
(map::~map): Remove.
(map::add_list): Manage all allocation for lists. Check for failed
memory allocation and return NULL if so.
(map::get_list): New method.
(map::del_list): Rename from erase. Check for legal incoming index
value.
(mmap64): Check for failed mmap_record memory allocation. Return
with MAP_FAILED and errno set to ENOMEM if so.
(munmap): Rearrange loop using new list and mmap_record accessor
functions. Rename loop index variables for better understanding.
Check if list can be deleted after last mmap_record in it has been
deleted.
(msync): Rearrange loop using new list and mmap_record accessor
functions. Rename loop index variables for better understanding.
(fixup_mmaps_after_fork): Ditto.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 48 | ||||
-rw-r--r-- | winsup/cygwin/mmap.cc | 545 |
2 files changed, 336 insertions, 257 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3a39394..332701f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,51 @@ +2003-09-04 Corinna Vinschen <corinna@vinschen.de> + + * mmap.cc: Restructure. Add, remove and rewrite comments throughout + for better readability. Change function names for better + understanding. + (MAP_SET): Accomodate name change from map_map_ to page_map_. + (MAP_CLR): Ditto. + (MAP_ISSET): Ditto. + (mmap_record::page_map_): Rename from page_map_. + (mmap_record::get_map): Remove. + (mmap_record::alloc_page_map): Rename from alloc_map. Return bool + indicating success of cygheap memory allocation. + (mmap_record::free_page_map): Rename from free_map. + (mmap_record::fixup_page_map): Rename from fixup_map. + (mmap_record::find_unused_pages): Rename from find_empty. + (mmap_record::map_pages): Rename from map_map. + (mmap_record::unmap_pages): Rename from unmap_map. + (class list): Make all class members private. + (list::list): Remove. + (list::~list): Remove. + (list::get_fd): New attribute reader. + (list::get_hash): Ditto. + (list::get_record): Ditto. + (list::add_record): Manage all allocation for mmap_records. Check + for failed memory allocation and return NULL if so. + (list::set): New function. + (list::del_record): Rename from erase. Return true if last mmap_record + has been deleted, false otherwise. Check for legal incoming index + value. + (list::erase): Remove erase/0. + (list::search_record): Rename from match. + (map::map): Remove. + (map::~map): Remove. + (map::add_list): Manage all allocation for lists. Check for failed + memory allocation and return NULL if so. + (map::get_list): New method. + (map::del_list): Rename from erase. Check for legal incoming index + value. + (mmap64): Check for failed mmap_record memory allocation. Return + with MAP_FAILED and errno set to ENOMEM if so. + (munmap): Rearrange loop using new list and mmap_record accessor + functions. Rename loop index variables for better understanding. + Check if list can be deleted after last mmap_record in it has been + deleted. + (msync): Rearrange loop using new list and mmap_record accessor + functions. Rename loop index variables for better understanding. + (fixup_mmaps_after_fork): Ditto. + 2003-09-03 Christopher Faylor <cgf@redhat.com> * cxx.cc (new): Fix formatting. Just return result of ccalloc rather diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index f38568f..af7d327 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -27,15 +27,29 @@ details. */ #define PGBITS (sizeof (DWORD)*8) #define MAPSIZE(pages) howmany ((pages), PGBITS) -#define MAP_SET(n) (map_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS))) -#define MAP_CLR(n) (map_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS))) -#define MAP_ISSET(n) (map_map_[(n)/PGBITS] & (1L << ((n) % PGBITS))) +#define MAP_SET(n) (page_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS))) +#define MAP_CLR(n) (page_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS))) +#define MAP_ISSET(n) (page_map_[(n)/PGBITS] & (1L << ((n) % PGBITS))) -/* - * Simple class used to keep a record of all current - * mmap areas in a process. Needed so that - * they can be duplicated after a fork(). - */ +/* Used for accessing the page file (anonymous mmaps). */ +static fhandler_disk_file fh_paging_file; + +/* Class structure used to keep a record of all current mmap areas + in a process. Needed for bookkeeping all mmaps in a process and + for duplicating all mmaps after fork() since mmaps are not propagated + to child processes by Windows. All information must be duplicated + by hand, see fixup_mmaps_after_fork(). + + The class structure: + + One member of class map per process, global variable mmapped_areas. + Contains a dynamic class list array. Each list entry represents all + mapping to a file, keyed by file descriptor and file name hash. + Each list entry contains a dynamic class mmap_record array. Each + mmap_record represents exactly one mapping. For each mapping, there's + an additional so called `page_map'. It's an array of bits, one bit + per mapped memory page. The bit is set if the page is accessible, + unset otherwise. */ class mmap_record { @@ -47,7 +61,7 @@ class mmap_record _off64_t offset_; DWORD size_to_map_; caddr_t base_address_; - DWORD *map_map_; + DWORD *page_map_; public: mmap_record (int fd, HANDLE h, DWORD ac, _off64_t o, DWORD s, caddr_t b) : @@ -58,15 +72,12 @@ class mmap_record offset_ (o), size_to_map_ (s), base_address_ (b), - map_map_ (NULL) + page_map_ (NULL) { if (fd >= 0 && !cygheap->fdtab.not_open (fd)) devtype_ = cygheap->fdtab[fd]->get_device (); } - /* Default Copy constructor/operator=/destructor are ok */ - - /* Simple accessors */ int get_fd () const { return fdesc_; } HANDLE get_handle () const { return mapping_handle_; } DWORD get_device () const { return devtype_; } @@ -74,22 +85,61 @@ class mmap_record DWORD get_offset () const { return offset_; } 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 (_off64_t off, DWORD len); - void free_map () { if (map_map_) cfree (map_map_); } - - DWORD find_empty (DWORD pages); - _off64_t map_map (_off64_t off, DWORD len); - BOOL unmap_map (caddr_t addr, DWORD len); - void fixup_map (void); + + bool alloc_page_map (_off64_t off, DWORD len); + void free_page_map () { if (page_map_) cfree (page_map_); } + void fixup_page_map (void); + + DWORD find_unused_pages (DWORD pages); + _off64_t map_pages (_off64_t off, DWORD len); + BOOL unmap_pages (caddr_t addr, DWORD len); int access (caddr_t address); fhandler_base *alloc_fh (); void free_fh (fhandler_base *fh); }; +class list +{ + private: + mmap_record *recs; + int nrecs, maxrecs; + int fd; + DWORD hash; + + public: + int get_fd () const { return fd; } + DWORD get_hash () const { return hash; } + mmap_record *get_record (int i) { return i >= nrecs ? NULL : recs + i; } + + void set (int nfd); + mmap_record *add_record (mmap_record r, _off64_t off, DWORD len); + bool del_record (int i); + void free_recs () { if (recs) cfree (recs); } + mmap_record *search_record (_off64_t off, DWORD len); + long search_record (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, + long start); +}; + +class map +{ + private: + list *lists; + int nlists, maxlists; + + 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); +}; + +/* This is the global map structure pointer. It's allocated once on the + first call to mmap64(). */ +static map *mmapped_areas; + DWORD -mmap_record::find_empty (DWORD pages) +mmap_record::find_unused_pages (DWORD pages) { DWORD mapped_pages = PAGE_CNT (size_to_map_); DWORD start; @@ -109,12 +159,15 @@ mmap_record::find_empty (DWORD pages) return (DWORD)-1; } -void -mmap_record::alloc_map (_off64_t off, DWORD len) +bool +mmap_record::alloc_page_map (_off64_t off, DWORD len) { /* Allocate one bit per page */ - map_map_ = (DWORD *) ccalloc (HEAP_MMAP, MAPSIZE (PAGE_CNT (size_to_map_)), - sizeof (DWORD)); + if (!(page_map_ = (DWORD *) ccalloc (HEAP_MMAP, + MAPSIZE (PAGE_CNT (size_to_map_)), + sizeof (DWORD)))) + return false; + if (wincap.virtual_protect_works_on_shared_pages ()) { DWORD old_prot; @@ -135,15 +188,16 @@ mmap_record::alloc_map (_off64_t off, DWORD len) while (len-- > 0) MAP_SET (off + len); } + return true; } _off64_t -mmap_record::map_map (_off64_t off, DWORD len) +mmap_record::map_pages (_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(). */ + Otherwise it's job is now done by alloc_page_map(). */ DWORD prot, old_prot; switch (access_mode_) { @@ -158,10 +212,10 @@ mmap_record::map_map (_off64_t off, DWORD len) break; } - debug_printf ("map_map (fd=%d, off=%D, len=%u)", fdesc_, off, len); + debug_printf ("map_pages (fd=%d, off=%D, len=%u)", fdesc_, off, len); len = PAGE_CNT (len); - if ((off = find_empty (len)) == (DWORD)-1) + if ((off = find_unused_pages (len)) == (DWORD)-1) return 0L; if (wincap.virtual_protect_works_on_shared_pages () && !VirtualProtect (base_address_ + off * getpagesize (), @@ -177,7 +231,7 @@ mmap_record::map_map (_off64_t off, DWORD len) } BOOL -mmap_record::unmap_map (caddr_t addr, DWORD len) +mmap_record::unmap_pages (caddr_t addr, DWORD len) { DWORD old_prot; DWORD off = addr - base_address_; @@ -186,20 +240,20 @@ mmap_record::unmap_map (caddr_t addr, DWORD len) if (wincap.virtual_protect_works_on_shared_pages () && !VirtualProtect (base_address_ + off * getpagesize (), len * getpagesize (), PAGE_NOACCESS, &old_prot)) - syscall_printf ("-1 = unmap_map (): %E"); + syscall_printf ("-1 = unmap_pages (): %E"); for (; len-- > 0; ++off) MAP_CLR (off); /* Return TRUE if all pages are free'd which may result in unmapping the whole chunk. */ for (len = MAPSIZE (PAGE_CNT (size_to_map_)); len > 0; ) - if (map_map_[--len]) + if (page_map_[--len]) return FALSE; return TRUE; } void -mmap_record::fixup_map () +mmap_record::fixup_page_map () { if (!wincap.virtual_protect_works_on_shared_pages ()) return; @@ -232,8 +286,6 @@ mmap_record::access (caddr_t address) return MAP_ISSET (off); } -static fhandler_disk_file fh_paging_file; - fhandler_base * mmap_record::alloc_fh () { @@ -258,57 +310,38 @@ mmap_record::free_fh (fhandler_base *fh) cfree (fh); } -class list { -public: - mmap_record *recs; - int nrecs, maxrecs; - int fd; - DWORD hash; - list (); - ~list (); - 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); - long match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, - long start); -}; - -list::list () -: nrecs (0), maxrecs (10), fd (0), hash (0) -{ - recs = (mmap_record *) cmalloc (HEAP_MMAP, 10 * sizeof (mmap_record)); -} - -list::~list () -{ - for (mmap_record *rec = recs; nrecs-- > 0; ++rec) - rec->free_map (); - cfree (recs); -} - mmap_record * list::add_record (mmap_record r, _off64_t off, DWORD len) { if (nrecs == maxrecs) { + mmap_record *new_recs; + if (maxrecs == 0) + new_recs = (mmap_record *) + cmalloc (HEAP_MMAP, 5 * sizeof (mmap_record)); + else + new_recs = (mmap_record *) + crealloc (recs, (maxrecs + 5) * sizeof (mmap_record)); + if (!new_recs) + return NULL; maxrecs += 5; - recs = (mmap_record *) crealloc (recs, maxrecs * sizeof (mmap_record)); + recs = new_recs; } recs[nrecs] = r; - recs[nrecs].alloc_map (off, len); + if (!recs[nrecs].alloc_page_map (off, len)) + return NULL; return recs + nrecs++; } /* Used in mmap() */ mmap_record * -list::match (_off64_t off, DWORD len) +list::search_record (_off64_t off, DWORD len) { if (fd == -1 && !off) { len = PAGE_CNT (len); for (int i = 0; i < nrecs; ++i) - if (recs[i].find_empty (len) != (DWORD)-1) + if (recs[i].find_unused_pages (len) != (DWORD)-1) return recs + i; } else @@ -324,7 +357,7 @@ list::match (_off64_t off, DWORD len) /* Used in munmap() */ long -list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, +list::search_record (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, _off_t start) { caddr_t low, high; @@ -346,41 +379,27 @@ list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, } void -list::erase (int i) -{ - recs[i].free_map (); - for (; i < nrecs-1; i++) - recs[i] = recs[i+1]; - nrecs--; -} - -void -list::erase () -{ - erase (nrecs-1); -} - -class map { -public: - list **lists; - int nlists, maxlists; - map (); - ~map (); - list *get_list_by_fd (int fd); - list *add_list (list *l, int fd); - void erase (int i); -}; - -map::map () +list::set (int nfd) { - lists = (list **) cmalloc (HEAP_MMAP, 10 * sizeof (list *)); - nlists = 0; - maxlists = 10; + if ((fd = nfd) != -1) + hash = cygheap->fdtab[fd]->get_namehash (); + nrecs = maxrecs = 0; + recs = NULL; } -map::~map () +bool +list::del_record (int i) { - cfree (lists); + if (i < nrecs) + { + recs[i].free_page_map (); + for (; i < nrecs - 1; i++) + recs[i] = recs[i + 1]; + nrecs--; + } + /* Return true if the list is empty which allows the caller to remove + this list from the list array. */ + return !nrecs; } list * @@ -388,50 +407,47 @@ map::get_list_by_fd (int fd) { int i; for (i=0; i<nlists; i++) -#if 0 /* The fd isn't sufficient since it could already be another file. */ - if (lists[i]->fd == fd -#else /* so we use the name hash value to identify the file unless - it's not an anonymous mapping. */ - if ((fd == -1 && lists[i]->fd == -1) - || (fd != -1 && lists[i]->hash == cygheap->fdtab[fd]->get_namehash ())) -#endif - return lists[i]; + /* The fd isn't sufficient since it could already be the fd of another + file. So we use the name hash value to identify the file unless + it's an anonymous mapping in which case the fd (-1) is sufficient. */ + if ((fd == -1 && lists[i].get_fd () == -1) + || (fd != -1 + && lists[i].get_hash () == cygheap->fdtab[fd]->get_namehash ())) + return lists + i; return 0; } list * -map::add_list (list *l, int fd) +map::add_list (int fd) { - l->fd = fd; - if (fd != -1) - l->hash = cygheap->fdtab[fd]->get_namehash (); if (nlists == maxlists) { + list *new_lists; + if (maxlists == 0) + new_lists = (list *) cmalloc (HEAP_MMAP, 5 * sizeof (list)); + else + new_lists = (list *) crealloc (lists, (maxlists + 5) * sizeof (list)); + if (!new_lists) + return NULL; maxlists += 5; - lists = (list **) crealloc (lists, maxlists * sizeof (list *)); + lists = new_lists; } - lists[nlists++] = l; - return lists[nlists-1]; + lists[nlists].set (fd); + return lists + nlists++; } void -map::erase (int i) +map::del_list (int i) { - for (; i < nlists-1; i++) - lists[i] = lists[i+1]; - nlists--; + if (i < nlists) + { + lists[i].free_recs (); + for (; i < nlists - 1; i++) + lists[i] = lists[i + 1]; + nlists--; + } } -/* - * 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 across a fork(), it - * needs to be specially handled by the fork code. - */ - -static map *mmapped_areas; - extern "C" caddr_t mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) { @@ -463,7 +479,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) if (mmapped_areas == NULL) { /* First mmap call, create STL map */ - mmapped_areas = new map; + mmapped_areas = (map *) ccalloc (HEAP_MMAP, 1, sizeof (map)); if (mmapped_areas == NULL) { set_errno (ENOMEM); @@ -530,9 +546,9 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED)) { mmap_record *rec; - if ((rec = map_list->match (off, len)) != NULL) + if ((rec = map_list->search_record (off, len)) != NULL) { - if ((off = rec->map_map (off, len)) == (_off64_t)-1) + if ((off = rec->map_pages (off, len)) == (_off64_t)-1) { syscall_printf ("-1 = mmap()"); ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, "mmap"); @@ -574,9 +590,8 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) return MAP_FAILED; } - /* Now we should have a successfully mmapped area. - Need to save it so forked children can reproduce it. - */ + /* At this point we should have a successfully mmapped area. + 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); @@ -587,7 +602,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) if (!map_list) { /* Create a new one */ - map_list = new list; + map_list = mmapped_areas->add_list (fd); if (!map_list) { fh->munmap (h, base, gran_len); @@ -596,11 +611,20 @@ 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; } - map_list = mmapped_areas->add_list (map_list, fd); } /* Insert into the list */ - mmap_record *rec = map_list->add_record (mmap_rec, off, len > gran_len ? gran_len : len); + mmap_record *rec = map_list->add_record (mmap_rec, off, + len > gran_len ? gran_len : len); + if (!rec) + { + fh->munmap (h, base, gran_len); + set_errno (ENOMEM); + syscall_printf ("-1 = mmap(): ENOMEM"); + ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); + return MAP_FAILED; + } + caddr_t ret = rec->get_address () + (off - gran_off); syscall_printf ("%x = mmap() succeeded", ret); ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); @@ -639,27 +663,33 @@ munmap (caddr_t addr, size_t len) /* Iterate through the map, unmap pages between addr and addr+len in all maps. */ - - for (int it = 0; it < mmapped_areas->nlists; ++it) + list *map_list; + for (int list_idx = 0; + (map_list = mmapped_areas->get_list (list_idx)); + ++list_idx) { - list *map_list = mmapped_areas->lists[it]; - if (map_list) - { - long li = -1; - caddr_t u_addr; - DWORD u_len; + long record_idx = -1; + caddr_t u_addr; + DWORD u_len; - while ((li = map_list->match(addr, len, u_addr, u_len, li)) >= 0) + while ((record_idx = map_list->search_record(addr, len, u_addr, + u_len, record_idx)) >= 0) + { + mmap_record *rec = map_list->get_record (record_idx); + if (rec->unmap_pages (u_addr, u_len)) { - mmap_record *rec = map_list->recs + li; - if (rec->unmap_map (u_addr, u_len)) - { - fhandler_base *fh = rec->alloc_fh (); - fh->munmap (rec->get_handle (), addr, len); - rec->free_fh (fh); + /* The whole record has been unmapped, so... */ + fhandler_base *fh = rec->alloc_fh (); + fh->munmap (rec->get_handle (), addr, len); + rec->free_fh (fh); - /* Delete the entry. */ - map_list->erase (li); + /* ...delete the record. */ + if (map_list->del_record (record_idx--)) + { + /* Yay, the last record has been removed from the list, + we can remove the list now, too. */ + mmapped_areas->del_list (list_idx--); + break; } } } @@ -700,33 +730,34 @@ msync (caddr_t addr, size_t len, int flags) /* Iterate through the map, looking for the mmapped area. Error if not found. */ - for (int it = 0; it < mmapped_areas->nlists; ++it) + list *map_list; + for (int list_idx = 0; + (map_list = mmapped_areas->get_list (list_idx)); + ++list_idx) { - list *map_list = mmapped_areas->lists[it]; - if (map_list != 0) + mmap_record *rec; + for (int record_idx = 0; + (rec = map_list->get_record (record_idx)); + ++record_idx) { - for (int li = 0; li < map_list->nrecs; ++li) + if (rec->access (addr)) { - mmap_record *rec = map_list->recs + li; - if (rec->access (addr)) - { - /* Check whole area given by len. */ - for (DWORD i = getpagesize (); i < len; ++i) - if (!rec->access (addr + i)) - goto invalid_address_range; - fhandler_base *fh = rec->alloc_fh (); - int ret = fh->msync (rec->get_handle (), addr, len, flags); - rec->free_fh (fh); - - if (ret) - syscall_printf ("%d = msync(): %E", ret); - else - syscall_printf ("0 = msync()"); - - ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, - "msync"); - return 0; - } + /* Check whole area given by len. */ + for (DWORD i = getpagesize (); i < len; ++i) + if (!rec->access (addr + i)) + goto invalid_address_range; + fhandler_base *fh = rec->alloc_fh (); + int ret = fh->msync (rec->get_handle (), addr, len, flags); + rec->free_fh (fh); + + if (ret) + syscall_printf ("%d = msync(): %E", ret); + else + syscall_printf ("0 = msync()"); + + ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, + "msync"); + return 0; } } } @@ -975,94 +1006,94 @@ fixup_mmaps_after_fork (HANDLE parent) return 0; /* Iterate through the map */ - for (int it = 0; it < mmapped_areas->nlists; ++it) + list *map_list; + for (int list_idx = 0; + (map_list = mmapped_areas->get_list (list_idx)); + ++list_idx) { - list *map_list = mmapped_areas->lists[it]; - if (map_list) + mmap_record *rec; + for (int record_idx = 0; + (rec = map_list->get_record (record_idx)); + ++record_idx) { - int li; - for (li = 0; li < map_list->nrecs; ++li) - { - mmap_record *rec = map_list->recs + li; - - debug_printf ("fd %d, h %x, access %x, offset %D, size %u, address %p", - rec->get_fd (), rec->get_handle (), rec->get_access (), - rec->get_offset (), rec->get_size (), rec->get_address ()); - - fhandler_base *fh = rec->alloc_fh (); - BOOL ret = fh->fixup_mmap_after_fork (rec->get_handle (), - rec->get_access (), - rec->get_offset (), - rec->get_size (), - rec->get_address ()); - rec->free_fh (fh); - if (!ret) - return -1; - if (rec->get_access () == FILE_MAP_COPY) - { - for (char *address = rec->get_address (); - address < rec->get_address () + rec->get_size (); - address += getpagesize ()) - if (rec->access (address) - && !ReadProcessMemory (parent, address, address, - getpagesize (), NULL)) + debug_printf ("fd %d, h %x, access %x, offset %D, size %u, address %p", + rec->get_fd (), rec->get_handle (), rec->get_access (), + rec->get_offset (), rec->get_size (), rec->get_address ()); + + fhandler_base *fh = rec->alloc_fh (); + BOOL ret = fh->fixup_mmap_after_fork (rec->get_handle (), + rec->get_access (), + rec->get_offset (), + rec->get_size (), + rec->get_address ()); + rec->free_fh (fh); + + if (!ret) + return -1; + if (rec->get_access () == FILE_MAP_COPY) + { + for (char *address = rec->get_address (); + address < rec->get_address () + rec->get_size (); + address += getpagesize ()) + if (rec->access (address) + && !ReadProcessMemory (parent, address, address, + getpagesize (), NULL)) + { + DWORD old_prot; + DWORD last_error = GetLastError (); + + if (last_error != ERROR_PARTIAL_COPY + && last_error != ERROR_NOACCESS + || !wincap.virtual_protect_works_on_shared_pages ()) { - DWORD old_prot; - DWORD last_error = GetLastError (); - - if (last_error != ERROR_PARTIAL_COPY - && last_error != ERROR_NOACCESS - || !wincap.virtual_protect_works_on_shared_pages ()) - { - system_printf ("ReadProcessMemory failed for " - "MAP_PRIVATE address %p, %E", - rec->get_address ()); - return -1; - } - if (!VirtualProtectEx (parent, - address, getpagesize (), - PAGE_READONLY, &old_prot)) + system_printf ("ReadProcessMemory failed for " + "MAP_PRIVATE address %p, %E", + rec->get_address ()); + return -1; + } + if (!VirtualProtectEx (parent, + address, getpagesize (), + PAGE_READONLY, &old_prot)) + { + system_printf ("VirtualProtectEx failed for " + "MAP_PRIVATE address %p, %E", + rec->get_address ()); + return -1; + } + else + { + BOOL ret; + DWORD dummy_prot; + + ret = ReadProcessMemory (parent, address, address, + getpagesize (), NULL); + if (!VirtualProtectEx(parent, + address, getpagesize (), + old_prot, &dummy_prot)) + system_printf ("WARNING: VirtualProtectEx to " + "return to previous state " + "in parent failed for " + "MAP_PRIVATE address %p, %E", + rec->get_address ()); + if (!VirtualProtect (address, getpagesize (), + old_prot, &dummy_prot)) + system_printf ("WARNING: VirtualProtect to copy " + "protection to child failed for" + "MAP_PRIVATE address %p, %E", + rec->get_address ()); + if (!ret) { - system_printf ("VirtualProtectEx failed for " + system_printf ("ReadProcessMemory (2nd try) " + "failed for " "MAP_PRIVATE address %p, %E", rec->get_address ()); return -1; } - else - { - BOOL ret; - DWORD dummy_prot; - - ret = ReadProcessMemory (parent, address, address, - getpagesize (), NULL); - if (!VirtualProtectEx(parent, - address, getpagesize (), - old_prot, &dummy_prot)) - system_printf ("WARNING: VirtualProtectEx to " - "return to previous state " - "in parent failed for " - "MAP_PRIVATE address %p, %E", - rec->get_address ()); - if (!VirtualProtect (address, getpagesize (), - old_prot, &dummy_prot)) - system_printf ("WARNING: VirtualProtect to copy " - "protection to child failed for" - "MAP_PRIVATE address %p, %E", - rec->get_address ()); - if (!ret) - { - system_printf ("ReadProcessMemory (2nd try) " - "failed for " - "MAP_PRIVATE address %p, %E", - rec->get_address ()); - return -1; - } - } } - } - rec->fixup_map (); + } } + rec->fixup_page_map (); } } |