* 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.
This commit is contained in:
		| @@ -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> | 2003-09-03  Christopher Faylor  <cgf@redhat.com> | ||||||
|  |  | ||||||
| 	* cxx.cc (new): Fix formatting.  Just return result of ccalloc rather | 	* cxx.cc (new): Fix formatting.  Just return result of ccalloc rather | ||||||
|   | |||||||
| @@ -27,15 +27,29 @@ details. */ | |||||||
| #define PGBITS		(sizeof (DWORD)*8) | #define PGBITS		(sizeof (DWORD)*8) | ||||||
| #define MAPSIZE(pages)	howmany ((pages), PGBITS) | #define MAPSIZE(pages)	howmany ((pages), PGBITS) | ||||||
|  |  | ||||||
| #define MAP_SET(n)	(map_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS))) | #define MAP_SET(n)	(page_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS))) | ||||||
| #define MAP_CLR(n)	(map_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS))) | #define MAP_CLR(n)	(page_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS))) | ||||||
| #define MAP_ISSET(n)	(map_map_[(n)/PGBITS] & (1L << ((n) % PGBITS))) | #define MAP_ISSET(n)	(page_map_[(n)/PGBITS] & (1L << ((n) % PGBITS))) | ||||||
|  |  | ||||||
| /* | /* Used for accessing the page file (anonymous mmaps). */ | ||||||
|  * Simple class used to keep a record of all current | static fhandler_disk_file fh_paging_file; | ||||||
|  * mmap areas in a process. Needed so that |  | ||||||
|  * they can be duplicated after a fork(). | /* 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 | class mmap_record | ||||||
| { | { | ||||||
| @@ -47,7 +61,7 @@ class mmap_record | |||||||
|     _off64_t offset_; |     _off64_t offset_; | ||||||
|     DWORD size_to_map_; |     DWORD size_to_map_; | ||||||
|     caddr_t base_address_; |     caddr_t base_address_; | ||||||
|     DWORD *map_map_; |     DWORD *page_map_; | ||||||
|  |  | ||||||
|   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, _off64_t o, DWORD s, caddr_t b) : | ||||||
| @@ -58,15 +72,12 @@ class mmap_record | |||||||
|        offset_ (o), |        offset_ (o), | ||||||
|        size_to_map_ (s), |        size_to_map_ (s), | ||||||
|        base_address_ (b), |        base_address_ (b), | ||||||
|        map_map_ (NULL) |        page_map_ (NULL) | ||||||
|       { |       { | ||||||
| 	if (fd >= 0 && !cygheap->fdtab.not_open (fd)) | 	if (fd >= 0 && !cygheap->fdtab.not_open (fd)) | ||||||
| 	  devtype_ = cygheap->fdtab[fd]->get_device (); | 	  devtype_ = cygheap->fdtab[fd]->get_device (); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|     /* Default Copy constructor/operator=/destructor are ok */ |  | ||||||
|  |  | ||||||
|     /* Simple accessors */ |  | ||||||
|     int get_fd () const { return fdesc_; } |     int get_fd () const { return fdesc_; } | ||||||
|     HANDLE get_handle () const { return mapping_handle_; } |     HANDLE get_handle () const { return mapping_handle_; } | ||||||
|     DWORD get_device () const { return devtype_; } |     DWORD get_device () const { return devtype_; } | ||||||
| @@ -74,22 +85,61 @@ class mmap_record | |||||||
|     DWORD get_offset () const { return offset_; } |     DWORD 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_; } | ||||||
|     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); |     bool alloc_page_map (_off64_t off, DWORD len); | ||||||
|     _off64_t map_map (_off64_t off, DWORD len); |     void free_page_map () { if (page_map_) cfree (page_map_); } | ||||||
|     BOOL unmap_map (caddr_t addr, DWORD len); |     void fixup_page_map (void); | ||||||
|     void fixup_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); |     int access (caddr_t address); | ||||||
|  |  | ||||||
|     fhandler_base *alloc_fh (); |     fhandler_base *alloc_fh (); | ||||||
|     void free_fh (fhandler_base *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 | DWORD | ||||||
| mmap_record::find_empty (DWORD pages) | mmap_record::find_unused_pages (DWORD pages) | ||||||
| { | { | ||||||
|   DWORD mapped_pages = PAGE_CNT (size_to_map_); |   DWORD mapped_pages = PAGE_CNT (size_to_map_); | ||||||
|   DWORD start; |   DWORD start; | ||||||
| @@ -109,12 +159,15 @@ mmap_record::find_empty (DWORD pages) | |||||||
|   return (DWORD)-1; |   return (DWORD)-1; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | bool | ||||||
| mmap_record::alloc_map (_off64_t off, DWORD len) | mmap_record::alloc_page_map (_off64_t off, DWORD len) | ||||||
| { | { | ||||||
|   /* Allocate one bit per page */ |   /* Allocate one bit per page */ | ||||||
|   map_map_ = (DWORD *) ccalloc (HEAP_MMAP, MAPSIZE (PAGE_CNT (size_to_map_)), |   if (!(page_map_ = (DWORD *) ccalloc (HEAP_MMAP, | ||||||
| 			        sizeof (DWORD)); | 				       MAPSIZE (PAGE_CNT (size_to_map_)), | ||||||
|  | 				       sizeof (DWORD)))) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|   if (wincap.virtual_protect_works_on_shared_pages ()) |   if (wincap.virtual_protect_works_on_shared_pages ()) | ||||||
|     { |     { | ||||||
|       DWORD old_prot; |       DWORD old_prot; | ||||||
| @@ -135,15 +188,16 @@ mmap_record::alloc_map (_off64_t off, DWORD len) | |||||||
|       while (len-- > 0) |       while (len-- > 0) | ||||||
| 	MAP_SET (off + len); | 	MAP_SET (off + len); | ||||||
|     } |     } | ||||||
|  |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| _off64_t | _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 |   /* Used ONLY if this mapping matches into the chunk of another already | ||||||
|      performed mapping in a special case of MAP_ANON|MAP_PRIVATE. |      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; |   DWORD prot, old_prot; | ||||||
|   switch (access_mode_) |   switch (access_mode_) | ||||||
|     { |     { | ||||||
| @@ -158,10 +212,10 @@ mmap_record::map_map (_off64_t off, DWORD len) | |||||||
|       break; |       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); |   len = PAGE_CNT (len); | ||||||
|  |  | ||||||
|   if ((off = find_empty (len)) == (DWORD)-1) |   if ((off = find_unused_pages (len)) == (DWORD)-1) | ||||||
|     return 0L; |     return 0L; | ||||||
|   if (wincap.virtual_protect_works_on_shared_pages () |   if (wincap.virtual_protect_works_on_shared_pages () | ||||||
|       && !VirtualProtect (base_address_ + off * getpagesize (), |       && !VirtualProtect (base_address_ + off * getpagesize (), | ||||||
| @@ -177,7 +231,7 @@ mmap_record::map_map (_off64_t off, DWORD len) | |||||||
| } | } | ||||||
|  |  | ||||||
| BOOL | BOOL | ||||||
| mmap_record::unmap_map (caddr_t addr, DWORD len) | mmap_record::unmap_pages (caddr_t addr, DWORD len) | ||||||
| { | { | ||||||
|   DWORD old_prot; |   DWORD old_prot; | ||||||
|   DWORD off = addr - base_address_; |   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 () |   if (wincap.virtual_protect_works_on_shared_pages () | ||||||
|       && !VirtualProtect (base_address_ + off * getpagesize (), |       && !VirtualProtect (base_address_ + off * getpagesize (), | ||||||
| 			  len * getpagesize (), PAGE_NOACCESS, &old_prot)) | 			  len * getpagesize (), PAGE_NOACCESS, &old_prot)) | ||||||
|     syscall_printf ("-1 = unmap_map (): %E"); |     syscall_printf ("-1 = unmap_pages (): %E"); | ||||||
|  |  | ||||||
|   for (; len-- > 0; ++off) |   for (; len-- > 0; ++off) | ||||||
|     MAP_CLR (off); |     MAP_CLR (off); | ||||||
|   /* Return TRUE if all pages are free'd which may result in unmapping |   /* Return TRUE if all pages are free'd which may result in unmapping | ||||||
|      the whole chunk. */ |      the whole chunk. */ | ||||||
|   for (len = MAPSIZE (PAGE_CNT (size_to_map_)); len > 0; ) |   for (len = MAPSIZE (PAGE_CNT (size_to_map_)); len > 0; ) | ||||||
|     if (map_map_[--len]) |     if (page_map_[--len]) | ||||||
|       return FALSE; |       return FALSE; | ||||||
|   return TRUE; |   return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| mmap_record::fixup_map () | mmap_record::fixup_page_map () | ||||||
| { | { | ||||||
|   if (!wincap.virtual_protect_works_on_shared_pages ()) |   if (!wincap.virtual_protect_works_on_shared_pages ()) | ||||||
|     return; |     return; | ||||||
| @@ -232,8 +286,6 @@ mmap_record::access (caddr_t address) | |||||||
|   return MAP_ISSET (off); |   return MAP_ISSET (off); | ||||||
| } | } | ||||||
|  |  | ||||||
| static fhandler_disk_file fh_paging_file; |  | ||||||
|  |  | ||||||
| fhandler_base * | fhandler_base * | ||||||
| mmap_record::alloc_fh () | mmap_record::alloc_fh () | ||||||
| { | { | ||||||
| @@ -258,57 +310,38 @@ mmap_record::free_fh (fhandler_base *fh) | |||||||
|     cfree (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 * | mmap_record * | ||||||
| list::add_record (mmap_record r, _off64_t off, DWORD len) | list::add_record (mmap_record r, _off64_t off, DWORD len) | ||||||
| { | { | ||||||
|   if (nrecs == maxrecs) |   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; |       maxrecs += 5; | ||||||
|       recs = (mmap_record *) crealloc (recs, maxrecs * sizeof (mmap_record)); |       recs = new_recs; | ||||||
|     } |     } | ||||||
|   recs[nrecs] = r; |   recs[nrecs] = r; | ||||||
|   recs[nrecs].alloc_map (off, len); |   if (!recs[nrecs].alloc_page_map (off, len)) | ||||||
|  |     return NULL; | ||||||
|   return recs + nrecs++; |   return recs + nrecs++; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Used in mmap() */ | /* Used in mmap() */ | ||||||
| mmap_record * | mmap_record * | ||||||
| list::match (_off64_t off, DWORD len) | list::search_record (_off64_t off, DWORD len) | ||||||
| { | { | ||||||
|   if (fd == -1 && !off) |   if (fd == -1 && !off) | ||||||
|     { |     { | ||||||
|       len = PAGE_CNT (len); |       len = PAGE_CNT (len); | ||||||
|       for (int i = 0; i < nrecs; ++i) |       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; | 	  return recs + i; | ||||||
|     } |     } | ||||||
|   else |   else | ||||||
| @@ -324,7 +357,7 @@ list::match (_off64_t off, DWORD len) | |||||||
|  |  | ||||||
| /* Used in munmap() */ | /* Used in munmap() */ | ||||||
| long | 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) | 	     _off_t start) | ||||||
| { | { | ||||||
|   caddr_t low, high; |   caddr_t low, high; | ||||||
| @@ -346,41 +379,27 @@ list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len, | |||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| list::erase (int i) | list::set (int nfd) | ||||||
| { | { | ||||||
|   recs[i].free_map (); |   if ((fd = nfd) != -1) | ||||||
|   for (; i < nrecs-1; i++) |     hash = cygheap->fdtab[fd]->get_namehash (); | ||||||
|     recs[i] = recs[i+1]; |   nrecs = maxrecs = 0; | ||||||
|  |   recs = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool | ||||||
|  | list::del_record (int i) | ||||||
|  | { | ||||||
|  |   if (i < nrecs) | ||||||
|  |     { | ||||||
|  |       recs[i].free_page_map (); | ||||||
|  |       for (; i < nrecs - 1; i++) | ||||||
|  | 	recs[i] = recs[i + 1]; | ||||||
|       nrecs--; |       nrecs--; | ||||||
| } |     } | ||||||
|  |   /* Return true if the list is empty which allows the caller to remove | ||||||
| void |      this list from the list array. */ | ||||||
| list::erase () |   return !nrecs; | ||||||
| { |  | ||||||
|   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 () |  | ||||||
| { |  | ||||||
|   lists = (list **) cmalloc (HEAP_MMAP, 10 * sizeof (list *)); |  | ||||||
|   nlists = 0; |  | ||||||
|   maxlists = 10; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| map::~map () |  | ||||||
| { |  | ||||||
|   cfree (lists); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| list * | list * | ||||||
| @@ -388,50 +407,47 @@ map::get_list_by_fd (int fd) | |||||||
| { | { | ||||||
|   int i; |   int i; | ||||||
|   for (i=0; i<nlists; i++) |   for (i=0; i<nlists; i++) | ||||||
| #if 0 /* The fd isn't sufficient since it could already be another file. */ |     /* The fd isn't sufficient since it could already be the fd of another | ||||||
|     if (lists[i]->fd == fd |        file.  So we use the name hash value to identify the file unless | ||||||
| #else /* 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. */ | ||||||
| 	 it's not an anonymous mapping. */ |     if ((fd == -1 && lists[i].get_fd () == -1) | ||||||
|     if ((fd == -1 && lists[i]->fd == -1) | 	|| (fd != -1 | ||||||
| 	|| (fd != -1 && lists[i]->hash == cygheap->fdtab[fd]->get_namehash ())) | 	    && lists[i].get_hash () == cygheap->fdtab[fd]->get_namehash ())) | ||||||
| #endif |       return lists + i; | ||||||
|       return lists[i]; |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| list * | 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) |   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; |       maxlists += 5; | ||||||
|       lists = (list **) crealloc (lists, maxlists * sizeof (list *)); |       lists = new_lists; | ||||||
|     } |     } | ||||||
|   lists[nlists++] = l; |   lists[nlists].set (fd); | ||||||
|   return lists[nlists-1]; |   return lists + nlists++; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| map::erase (int i) | map::del_list (int i) | ||||||
| { | { | ||||||
|   for (; i < nlists-1; i++) |   if (i < nlists) | ||||||
|     lists[i] = lists[i+1]; |     { | ||||||
|  |       lists[i].free_recs (); | ||||||
|  |       for (; i < nlists - 1; i++) | ||||||
|  |         lists[i] = lists[i + 1]; | ||||||
|       nlists--; |       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 | extern "C" caddr_t | ||||||
| mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off) | 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) |   if (mmapped_areas == NULL) | ||||||
|     { |     { | ||||||
|       /* First mmap call, create STL map */ |       /* First mmap call, create STL map */ | ||||||
|       mmapped_areas = new map; |       mmapped_areas = (map *) ccalloc (HEAP_MMAP, 1, sizeof (map)); | ||||||
|       if (mmapped_areas == NULL) |       if (mmapped_areas == NULL) | ||||||
| 	{ | 	{ | ||||||
| 	  set_errno (ENOMEM); | 	  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)) |   if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED)) | ||||||
|     { |     { | ||||||
|       mmap_record *rec; |       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()"); | 	      syscall_printf ("-1 = mmap()"); | ||||||
| 	      ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, "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; |       return MAP_FAILED; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   /* Now we should have a successfully mmapped area. |   /* At this point we should have a successfully mmapped area. | ||||||
|      Need to save it so forked children can reproduce it. |      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, 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) |   if (!map_list) | ||||||
|     { |     { | ||||||
|       /* Create a new one */ |       /* Create a new one */ | ||||||
|       map_list = new list; |       map_list = mmapped_areas->add_list (fd); | ||||||
|       if (!map_list) |       if (!map_list) | ||||||
| 	{ | 	{ | ||||||
| 	  fh->munmap (h, base, gran_len); | 	  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"); | 	  ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); | ||||||
| 	  return MAP_FAILED; | 	  return MAP_FAILED; | ||||||
| 	} | 	} | ||||||
|       map_list = mmapped_areas->add_list (map_list, fd); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* Insert into the list */ |   /* 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); |   caddr_t ret = rec->get_address () + (off - gran_off); | ||||||
|   syscall_printf ("%x = mmap() succeeded", ret); |   syscall_printf ("%x = mmap() succeeded", ret); | ||||||
|   ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap"); |   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 |   /* Iterate through the map, unmap pages between addr and addr+len | ||||||
|      in all maps. */ |      in all maps. */ | ||||||
|  |   list *map_list; | ||||||
|   for (int it = 0; it < mmapped_areas->nlists; ++it) |   for (int list_idx = 0; | ||||||
|  |        (map_list = mmapped_areas->get_list (list_idx)); | ||||||
|  |        ++list_idx) | ||||||
|     { |     { | ||||||
|       list *map_list = mmapped_areas->lists[it]; |       long record_idx = -1; | ||||||
|       if (map_list) |  | ||||||
| 	{ |  | ||||||
| 	  long li = -1; |  | ||||||
|       caddr_t u_addr; |       caddr_t u_addr; | ||||||
|       DWORD u_len; |       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->recs + li; | 	  mmap_record *rec = map_list->get_record (record_idx); | ||||||
| 	      if (rec->unmap_map (u_addr, u_len)) | 	  if (rec->unmap_pages (u_addr, u_len)) | ||||||
| 	    { | 	    { | ||||||
|  | 	      /* The whole record has been unmapped, so... */ | ||||||
| 	      fhandler_base *fh = rec->alloc_fh (); | 	      fhandler_base *fh = rec->alloc_fh (); | ||||||
| 	      fh->munmap (rec->get_handle (), addr, len); | 	      fh->munmap (rec->get_handle (), addr, len); | ||||||
| 	      rec->free_fh (fh); | 	      rec->free_fh (fh); | ||||||
|  |  | ||||||
| 		  /* Delete the entry. */ | 	      /* ...delete the record. */ | ||||||
| 		  map_list->erase (li); | 	      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,14 +730,16 @@ msync (caddr_t addr, size_t len, int flags) | |||||||
|   /* Iterate through the map, looking for the mmapped area. |   /* Iterate through the map, looking for the mmapped area. | ||||||
|      Error if not found. */ |      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]; |       mmap_record *rec; | ||||||
|       if (map_list != 0) |       for (int record_idx = 0; | ||||||
|  |       	   (rec = map_list->get_record (record_idx)); | ||||||
|  | 	   ++record_idx) | ||||||
| 	{ | 	{ | ||||||
| 	  for (int li = 0; li < map_list->nrecs; ++li) |  | ||||||
| 	    { |  | ||||||
| 	      mmap_record *rec = map_list->recs + li; |  | ||||||
| 	  if (rec->access (addr)) | 	  if (rec->access (addr)) | ||||||
| 	    { | 	    { | ||||||
| 	      /* Check whole area given by len. */ | 	      /* Check whole area given by len. */ | ||||||
| @@ -729,7 +761,6 @@ msync (caddr_t addr, size_t len, int flags) | |||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
| invalid_address_range: | invalid_address_range: | ||||||
|   /* SUSv2: Return code if indicated memory was not mapped is ENOMEM. */ |   /* SUSv2: Return code if indicated memory was not mapped is ENOMEM. */ | ||||||
| @@ -975,15 +1006,16 @@ fixup_mmaps_after_fork (HANDLE parent) | |||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   /* Iterate through the map */ |   /* 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]; |       mmap_record *rec; | ||||||
|       if (map_list) |       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", | 	  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_fd (), rec->get_handle (), rec->get_access (), | ||||||
| @@ -1061,8 +1093,7 @@ fixup_mmaps_after_fork (HANDLE parent) | |||||||
| 		      } | 		      } | ||||||
| 		  } | 		  } | ||||||
| 	    } | 	    } | ||||||
| 	      rec->fixup_map (); | 	  rec->fixup_page_map (); | ||||||
| 	    } |  | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user