From 392323df55fcf19800d8a5f4b943d63c092eedcc Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 5 May 2011 09:05:04 +0000 Subject: [PATCH] * fhandler.cc (is_at_eof): Drop static storage class. Drop err parameter since we don't change the Win32 error here anymore. (fhandler_base::raw_read): Accommodate change to is_at_eof. * fhandler_disk_file.cc (fhandler_disk_file::pread): In binary mode use direct call to NtReadFile, rather than lseek/read. (fhandler_disk_file::pwrite): In binary mode use direct call to NtWriteFile, rather than lseek/write. --- winsup/cygwin/ChangeLog | 11 ++++++ winsup/cygwin/fhandler.cc | 7 ++-- winsup/cygwin/fhandler_disk_file.cc | 58 +++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 47fcb33e4..289b7288c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2011-05-05 Corinna Vinschen + + * fhandler.cc (is_at_eof): Drop static storage class. Drop err + parameter since we don't change the Win32 error here anymore. + (fhandler_base::raw_read): Accommodate change to is_at_eof. + + * fhandler_disk_file.cc (fhandler_disk_file::pread): In binary mode use + direct call to NtReadFile, rather than lseek/read. + (fhandler_disk_file::pwrite): In binary mode use direct call to + NtWriteFile, rather than lseek/write. + 2011-05-05 Corinna Vinschen * dcrt0.cc (dll_crt0_1): Reset locale to "C" even when dynamically diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 858be1088..a4a256383 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -163,8 +163,8 @@ char *fhandler_base::get_proc_fd_name (char *buf) /* Detect if we are sitting at EOF for conditions where Windows returns an error but UNIX doesn't. */ -static int __stdcall -is_at_eof (HANDLE h, DWORD err) +int __stdcall +is_at_eof (HANDLE h) { IO_STATUS_BLOCK io; FILE_POSITION_INFORMATION fpi; @@ -176,7 +176,6 @@ is_at_eof (HANDLE h, DWORD err) FilePositionInformation)) && fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart) return 1; - SetLastError (err); return 0; } @@ -237,7 +236,7 @@ retry: /* `bytes_read' is supposedly valid. */ break; case ERROR_NOACCESS: - if (is_at_eof (get_handle (), errcode)) + if (is_at_eof (get_handle ())) { bytes_read = 0; break; diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 89501cc71..1c586f3c6 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -1415,6 +1415,47 @@ out: ssize_t __stdcall fhandler_disk_file::pread (void *buf, size_t count, _off64_t offset) { + /* In binary mode, we can use an atomic NtReadFile call. */ + if (rbinary ()) + { + extern int __stdcall is_at_eof (HANDLE h); + NTSTATUS status; + IO_STATUS_BLOCK io; + LARGE_INTEGER off = { QuadPart:offset }; + + status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, buf, count, + &off, NULL); + if (!NT_SUCCESS (status)) + { + if (pc.isdir ()) + { + set_errno (EISDIR); + return -1; + } + if (status == (NTSTATUS) STATUS_ACCESS_VIOLATION) + { + if (is_at_eof (get_handle ())) + return 0; + switch (mmap_is_attached_or_noreserve (buf, count)) + { + case MMAP_NORESERVE_COMMITED: + status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, + buf, count, &off, NULL); + if (NT_SUCCESS (status)) + return io.Information; + break; + case MMAP_RAISE_SIGBUS: + raise (SIGBUS); + default: + break; + } + } + __seterrno_from_nt_status (status); + return -1; + } + return io.Information; + } + /* Text mode stays slow and non-atomic. */ ssize_t res; _off64_t curpos = lseek (0, SEEK_CUR); if (curpos < 0 || lseek (offset, SEEK_SET) < 0) @@ -1435,6 +1476,23 @@ fhandler_disk_file::pread (void *buf, size_t count, _off64_t offset) ssize_t __stdcall fhandler_disk_file::pwrite (void *buf, size_t count, _off64_t offset) { + /* In binary mode, we can use an atomic NtWriteFile call. */ + if (wbinary ()) + { + NTSTATUS status; + IO_STATUS_BLOCK io; + LARGE_INTEGER off = { QuadPart:offset }; + + status = NtWriteFile (get_handle (), NULL, NULL, NULL, &io, buf, count, + &off, NULL); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return -1; + } + return io.Information; + } + /* Text mode stays slow and non-atomic. */ int res; _off64_t curpos = lseek (0, SEEK_CUR); if (curpos < 0 || lseek (offset, SEEK_SET) < 0)