diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2006-07-19 15:17:04 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2006-07-19 15:17:04 +0400 |
commit | 62b9fc5940c2bc20035e648cb97dd23fa9a7b5d9 (patch) | |
tree | f16817140dec33083f028d40937451930bb85aeb | |
parent | c2d7650c68ad01823f8b7f5febec5708fc2ac0d6 (diff) |
* Correctly merge HEAD into cv-branch.
-rw-r--r-- | winsup/cygwin/mmap.cc | 90 |
1 files changed, 55 insertions, 35 deletions
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 97966515e..1c1afba57 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -900,44 +900,64 @@ map::del_list (unsigned i) } /* This function is called from exception_handler when a segmentation - violation has happened. We have two cases to check here. + violation has occurred. It should also be called from all Cygwin + functions that want to support passing noreserve mmap page addresses + to Windows system calls. In that case, it should be called only after + a system call indicates that the application buffer passed had an + invalid virtual address to avoid any performance impact in non-noreserve + cases. - First, is it an address within "attached" mmap pages (indicated by - the __PROT_ATTACH protection, see there)? In this case the function - returns 1 and the exception_handler raises SIGBUS, as demanded by the - memory protection extension described in SUSv3 (see the mmap man - page). - - Second, check if the address is within "noreserve" mmap pages - (indicated by MAP_NORESERVE flag). If so, the function calls - VirtualAlloc to commit the page and returns 2. The exception handler - then just returns with 0 and the affected application retries the - failing memory access. If VirtualAlloc fails, the function returns - 1, so that the exception handler raises a SIGBUS, as described in the - MAP_NORESERVE man pages for Linux and Solaris. - - In any other case 0 is returned and a normal SIGSEGV is raised. */ -int -mmap_is_attached_or_noreserve_page (ULONG_PTR addr) + Check if the address range is all within noreserve mmap regions. If so, + call VirtualAlloc to commit the pages and return MMAP_NORESERVE_COMMITED + on success. If the page has __PROT_ATTACH (SUSv3 memory protection + extension), or if VirutalAlloc fails, return MMAP_RAISE_SIGBUS. + Otherwise, return MMAP_NONE if the address range is not covered by an + attached or noreserve map. + + On MAP_NORESERVE_COMMITED, the exeception handler should return 0 to + allow the application to retry the memory access, or the calling Cygwin + function should retry the Windows system call. */ +mmap_region_status +mmap_is_attached_or_noreserve (void *addr, size_t len) { - list *map_list; - long record_idx; - caddr_t u_addr; - DWORD u_len; - DWORD pagesize = getsystempagesize (); + list *map_list = mmapped_areas.get_list_by_fd (-1); - addr = rounddown (addr, pagesize); - if (!(map_list = mmapped_areas.get_list_by_fd (-1))) - return 0; - if ((record_idx = map_list->search_record ((caddr_t)addr, pagesize, - u_addr, u_len, -1)) < 0) - return 0; - if (map_list->get_record (record_idx)->attached ()) - return 1; - if (!map_list->get_record (record_idx)->noreserve ()) - return 0; - DWORD new_prot = map_list->get_record (record_idx)->gen_protect (); - return VirtualAlloc ((void *)addr, pagesize, MEM_COMMIT, new_prot) ? 2 : 1; + size_t pagesize = getpagesize (); + caddr_t start_addr = (caddr_t) rounddown ((uintptr_t) addr, pagesize); + len += ((caddr_t) addr - start_addr); + len = roundup2 (len, pagesize); + + if (map_list == NULL) + return MMAP_NONE; + + while (len > 0) + { + caddr_t u_addr; + DWORD u_len; + long record_idx = map_list->search_record (start_addr, len, + u_addr, u_len, -1); + if (record_idx < 0) + return MMAP_NONE; + + mmap_record *rec = map_list->get_record (record_idx); + if (rec->attached ()) + return MMAP_RAISE_SIGBUS; + if (!rec->noreserve ()) + return MMAP_NONE; + + size_t commit_len = u_len - (start_addr - u_addr); + if (commit_len > len) + commit_len = len; + + if (!VirtualAlloc (start_addr, commit_len, MEM_COMMIT, + rec->gen_protect ())) + return MMAP_RAISE_SIGBUS; + + start_addr += commit_len; + len -= commit_len; + } + + return MMAP_NORESERVE_COMMITED; } static caddr_t |