public inbox for cygwin-cvs@sourceware.org help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org> To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: pipe: Stop counting reader and read all available data. Date: Tue, 14 Sep 2021 15:06:49 +0000 (GMT) [thread overview] Message-ID: <20210914150649.9DE013857819@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=fadbedd9ca5f9117aba38b8aa0d7bf705d4c8d5d commit fadbedd9ca5f9117aba38b8aa0d7bf705d4c8d5d Author: Takashi Yano <takashi.yano@nifty.ne.jp> 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
reply other threads:[~2021-09-14 15:06 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210914150649.9DE013857819@sourceware.org \ --to=corinna@sourceware.org \ --cc=cygwin-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).