On Fri, 14 Jul 2006, Corinna Vinschen wrote: > The idea is to have features working for most cases and then > to get it working gradually better.
Well, in that spirit then, the attached patch allows read and varients to use untouched noreserve mappings as buffers. If this is accepted, I'll consider doing something similar for recvmsg and recvfrom. That should cover the majority of cases, I believe. 2006-07-17 Brian Ford <[EMAIL PROTECTED]> * winsup.h (mmap_commit_noreserve_pages): New prototype. * mmap.cc (fhandler_base::raw_read): New function. * fhandler.cc (fhandler_base::raw_read): Call it for INVALID_PARAMETER errors, and retry on success to allow reads into untouched MAP_NORESERVE buffers. -- Brian Ford Lead Realtime Software Engineer VITAL - Visual Simulation Systems FlightSafety International the best safety device in any aircraft is a well-trained crew... .
Index: fhandler.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.cc,v retrieving revision 1.256 diff -u -p -u -p -r1.256 fhandler.cc --- fhandler.cc 13 Jul 2006 20:56:24 -0000 1.256 +++ fhandler.cc 17 Jul 2006 17:02:10 -0000 @@ -223,8 +223,10 @@ fhandler_base::raw_read (void *ptr, size HANDLE h = NULL; /* grumble */ int prio = 0; /* ditto */ + int try_noreserve = 1; DWORD len = ulen; +retry: ulen = (size_t) -1; if (read_state) { @@ -259,8 +261,14 @@ fhandler_base::raw_read (void *ptr, size bytes_read = 0; break; } - case ERROR_INVALID_FUNCTION: case ERROR_INVALID_PARAMETER: + if (try_noreserve) + { + try_noreserve = 0; + if (mmap_commit_noreserve_pages (ptr, len)) + goto retry; + } + case ERROR_INVALID_FUNCTION: case ERROR_INVALID_HANDLE: if (pc.isdir ()) { Index: mmap.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/mmap.cc,v retrieving revision 1.130 diff -u -p -u -p -r1.130 mmap.cc --- mmap.cc 13 Jul 2006 10:29:21 -0000 1.130 +++ mmap.cc 17 Jul 2006 17:02:11 -0000 @@ -899,6 +899,58 @@ map::del_list (unsigned i) } } +/* This function should be called by all Cygwin functions that want to + support passing noreserve mmap page addresses to Windows system calls. + 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. + + Check if the address range is all within "noreserve" mmap regions. + If so, call VirtualAlloc to commit the pages and return 1 on success. + If VirtualAlloc fails, raise SIGBUS and return 0. Also return 0 if + the address range was not covered by a noreserve map. + + On success, the calling Cygwin function should retry the Windows system + call. */ +int +mmap_commit_noreserve_pages (void *addr, size_t len) +{ + list *map_list = mmapped_areas.get_list_by_fd (-1); + + if (map_list == NULL) + return 0; + + while (len > 0) + { + caddr_t u_addr; + DWORD u_len; + long record_idx = map_list->search_record ((caddr_t)addr, 1, + u_addr, u_len, -1); + if (record_idx < 0) + return 0; + + mmap_record *rec = map_list->get_record (record_idx); + if (!rec->noreserve ()) + return 0; + + size_t commit_len = u_len - ((char *)addr - u_addr); + if (commit_len > len) + commit_len = len; + + if (VirtualAlloc (addr, commit_len, MEM_COMMIT, rec->gen_protect ()) + == NULL) + { + raise(SIGBUS); + return 0; + } + + addr = (char *)addr + commit_len; + len -= commit_len; + } + + return 1; +} + /* This function is called from exception_handler when a segmentation violation has happened. We have two cases to check here. Index: winsup.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v retrieving revision 1.189 diff -u -p -u -p -r1.189 winsup.h --- winsup.h 13 Jul 2006 08:33:34 -0000 1.189 +++ winsup.h 17 Jul 2006 17:02:11 -0000 @@ -300,6 +300,7 @@ size_t getsystempagesize (); /* mmap functions. */ void mmap_init (); int mmap_is_attached_or_noreserve_page (ULONG_PTR addr); +int mmap_commit_noreserve_pages (void *addr, size_t len); int winprio_to_nice (DWORD) __attribute__ ((regparm (1))); DWORD nice_to_winprio (int &) __attribute__ ((regparm (1)));