From a24e8ff255163cf5af98f6f684c0d3ad17f945c7 Mon Sep 17 00:00:00 2001 From: Ivan Zhakov Date: Mon, 27 May 2019 07:12:13 +0000 Subject: Optimize overlapped I/O for files and pipes on Windows. * file_io/win32/open.c (read_with_timeout, apr_file_write): Check that overlapped I/O operation already completed by macro HasOverlappedIoCompleted() before calling kernel via WaitForSingleObject(). git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1860108 13f79535-47bb-0310-9956-ffa450edef68 --- file_io/win32/readwrite.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'file_io') diff --git a/file_io/win32/readwrite.c b/file_io/win32/readwrite.c index 7e25b490d..310d7905a 100644 --- a/file_io/win32/readwrite.c +++ b/file_io/win32/readwrite.c @@ -80,14 +80,24 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le else { rv = apr_get_os_error(); if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { - /* Wait for the pending i/o, timeout converted from us to ms - * Note that we loop if someone gives up the event. - * - * NOTE: We do not handle WAIT_ABANDONED here because they - * can be returned only when waiting for mutex. - */ - res = apr_wait_for_single_object(file->pOverlapped->hEvent, - file->timeout); + /* It seems that ReadFile() return ERROR_IO_PENDING even + * when I/O operation completed syncronously. + * Use fast macro to check that overlapped I/O already + * completed to avoid kernel call. + */ + if (HasOverlappedIoCompleted(file->pOverlapped)) { + res = WAIT_OBJECT_0; + } + else { + /* Wait for the pending i/o, timeout converted from us to ms + * Note that we loop if someone gives up the event. + * + * NOTE: We do not handle WAIT_ABANDONED here because they + * can be returned only when waiting for mutex. + */ + res = apr_wait_for_single_object(file->pOverlapped->hEvent, + file->timeout); + } /* There is one case that represents entirely * successful operations, otherwise we will cancel @@ -489,8 +499,18 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a DWORD res; - res = apr_wait_for_single_object(thefile->pOverlapped->hEvent, - thefile->timeout); + /* It seems that WriteFile() return ERROR_IO_PENDING even + * when I/O operation completed syncronously. + * Use fast macro to check that overlapped I/O already + * completed to avoid kernel call. + */ + if (HasOverlappedIoCompleted(thefile->pOverlapped)) { + res = WAIT_OBJECT_0; + } + else { + res = apr_wait_for_single_object(thefile->pOverlapped->hEvent, + thefile->timeout); + } /* There is one case that represents entirely * successful operations, otherwise we will cancel -- cgit v1.2.1