From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 9DE013857819; Tue, 14 Sep 2021 15:06:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9DE013857819 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: pipe: Stop counting reader and read all available data. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/master X-Git-Oldrev: 085fc12948881e624921f568a29881ce38795368 X-Git-Newrev: fadbedd9ca5f9117aba38b8aa0d7bf705d4c8d5d Message-Id: <20210914150649.9DE013857819@sourceware.org> Date: Tue, 14 Sep 2021 15:06:49 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Sep 2021 15:06:49 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=fadbedd9ca5f9117aba38b8aa0d7bf705d4c8d5d commit fadbedd9ca5f9117aba38b8aa0d7bf705d4c8d5d Author: Takashi Yano Date: Mon Sep 6 20:12:16 2021 +0900 Cygwin: pipe: Stop counting reader and read all available data. - By guarding read with read_mtx, no more than one ReadFile can be called simultaneously. So couting read handles is no longer necessary. - Make raw_read code as similar as possible to raw_write code. Diff: --- winsup/cygwin/fhandler_pipe.cc | 100 ++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc index 68974eb80..fe0bf0ca2 100644 --- a/winsup/cygwin/fhandler_pipe.cc +++ b/winsup/cygwin/fhandler_pipe.cc @@ -221,12 +221,10 @@ fhandler_pipe::get_proc_fd_name (char *buf) void __reg3 fhandler_pipe::raw_read (void *ptr, size_t& len) { - NTSTATUS status; + size_t nbytes = 0; + NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK io; HANDLE evt = NULL; - DWORD waitret = WAIT_OBJECT_0; - bool keep_looping = false; - size_t orig_len = len; if (!len) return; @@ -239,43 +237,59 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) return; } - do + DWORD timeout = is_nonblocking () ? 0 : INFINITE; + DWORD waitret = cygwait (read_mtx, timeout); + switch (waitret) { - len = orig_len; - keep_looping = false; + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + set_errno (EAGAIN); + len = (size_t) -1; + return; + default: + set_errno (EINTR); + len = (size_t) -1; + return; + } + while (nbytes < len) + { + ULONG_PTR nbytes_now = 0; + size_t left = len - nbytes; + ULONG len1 = (ULONG) left; + waitret = WAIT_OBJECT_0; + if (evt) ResetEvent (evt); if (!is_nonblocking ()) { FILE_PIPE_LOCAL_INFORMATION fpli; - ULONG reader_count; - ULONG max_len = 64; - - WaitForSingleObject (read_mtx, INFINITE); - /* If the pipe is empty, don't request more bytes than half the - pipe buffer size. Every pending read lowers WriteQuotaAvailable - on the write side and thus affects select's ability to return - more or less reliable info whether a write succeeds or not. - - Let the size of the request depend on the number of readers - at the time. */ + /* If the pipe is empty, don't request more bytes than pipe + buffer size - 1. Pending read lowers WriteQuotaAvailable on + the write side and thus affects select's ability to return + more or less reliable info whether a write succeeds or not. */ + ULONG chunk = max_atomic_write - 1; status = NtQueryInformationFile (get_handle (), &io, &fpli, sizeof (fpli), FilePipeLocalInformation); - if (NT_SUCCESS (status) && fpli.ReadDataAvailable == 0) + if (NT_SUCCESS (status)) { - reader_count = get_obj_handle_count (get_handle ()); - if (reader_count < 10) - max_len = fpli.InboundQuota / (2 * reader_count); - if (len > max_len) - len = max_len; + if (fpli.ReadDataAvailable > 0) + chunk = left; + else if (nbytes != 0) + break; + else + chunk = fpli.InboundQuota - 1; } + else if (nbytes != 0) + break; + + if (len1 > chunk) + len1 = chunk; } status = NtReadFile (get_handle (), evt, NULL, NULL, &io, ptr, - len, NULL, NULL); - if (!is_nonblocking ()) - ReleaseMutex (read_mtx); + len1, NULL, NULL); if (evt && status == STATUS_PENDING) { waitret = cygwait (evt); @@ -292,13 +306,13 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) set_errno (EBADF); else __seterrno (); - len = (size_t) -1; + nbytes = (size_t) -1; } else if (NT_SUCCESS (status)) { - len = io.Information; - if (len == 0) - keep_looping = true; + nbytes_now = io.Information; + ptr = ((char *) ptr) + nbytes_now; + nbytes += nbytes_now; } else { @@ -308,40 +322,46 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) case STATUS_END_OF_FILE: case STATUS_PIPE_BROKEN: /* This is really EOF. */ - len = 0; break; case STATUS_MORE_ENTRIES: case STATUS_BUFFER_OVERFLOW: /* `io.Information' is supposedly valid. */ - len = io.Information; - if (len == 0) - keep_looping = true; + nbytes_now = io.Information; + ptr = ((char *) ptr) + nbytes_now; + nbytes += nbytes_now; break; case STATUS_PIPE_LISTENING: case STATUS_PIPE_EMPTY: + if (nbytes != 0) + break; if (is_nonblocking ()) { set_errno (EAGAIN); - len = (size_t) -1; + nbytes = (size_t) -1; break; } fallthrough; default: __seterrno_from_nt_status (status); - len = (size_t) -1; + nbytes = (size_t) -1; break; } } - } while (keep_looping); + + if (nbytes_now == 0) + break; + } + ReleaseMutex (read_mtx); if (evt) CloseHandle (evt); - if (status == STATUS_THREAD_SIGNALED) + if (status == STATUS_THREAD_SIGNALED && nbytes == 0) { set_errno (EINTR); - len = (size_t) -1; + nbytes = (size_t) -1; } else if (status == STATUS_THREAD_CANCELED) pthread::static_cancel_self (); + len = nbytes; } ssize_t __reg3