From 9636c4262e16846fb595d1fffa711ca4aa70dc47 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 13 Mar 2011 20:20:58 +0000 Subject: * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Remove special treatment for ERROR_NO_SYSTEM_RESOURCES. Cancel I/O and reset the overlapped handle on error. (fhandler_base_overlapped::write_overlapped): Limit writes to max_atomic_write bytes in blocking case. Incorporate code from now-defunct write_overlapped_fallback. Fix serious oversight where ptr was not advanced as buffer was written. (fhandler_base_overlapped::write_overlapped_fallback): Eliminate. * fhandler.h (fhandler_base_overlapped::write_overlapped_fallback): Ditto for declaration. (DEFAULT_PIPEBUFSIZE): Lower size to slightly less than documented worst-case atomic write size. (fhandler_overlapped::wait_return): Remove unused element. --- winsup/cygwin/ChangeLog | 18 +++++++- winsup/cygwin/fhandler.cc | 115 +++++++++++++++------------------------------- winsup/cygwin/fhandler.h | 6 +-- 3 files changed, 56 insertions(+), 83 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index a01d83b..2ff87cb 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +2011-03-13 Christopher Faylor + + * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Remove + special treatment for ERROR_NO_SYSTEM_RESOURCES. Cancel I/O and reset + the overlapped handle on error. + (fhandler_base_overlapped::write_overlapped): Limit writes to + max_atomic_write bytes in blocking case. Incorporate code from + now-defunct write_overlapped_fallback. Fix serious oversight where ptr + was not advanced as buffer was written. + (fhandler_base_overlapped::write_overlapped_fallback): Eliminate. + * fhandler.h (fhandler_base_overlapped::write_overlapped_fallback): + Ditto for declaration. + (DEFAULT_PIPEBUFSIZE): Lower size to slightly less than documented + worst-case atomic write size. + (fhandler_overlapped::wait_return): Remove unused element. + 2011-03-09 Christopher Faylor * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle @@ -10,7 +26,7 @@ (fhandler_base_overlapped::write_overlapped_fallback): Add some more comments. -2011-03-09 Christopher Faylor +2011-03-09 Christopher Faylor * fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops! Accommodate change in arguments to wait_overlapped. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 56d2872..79c9a91 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1733,9 +1733,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte wait_return res; DWORD err = GetLastError (); - if (err == ERROR_NO_SYSTEM_RESOURCES) - res = overlapped_fallback; - else if (nonblocking) + if (nonblocking) { if (!inres && err != ERROR_IO_PENDING) res = overlapped_error; @@ -1806,6 +1804,9 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte else { debug_printf ("err %u", err); + HANDLE h = writing ? get_output_handle () : get_handle (); + CancelIo (h); + ResetEvent (get_overlapped ()); __seterrno_from_win_error (err); *bytes = (DWORD) -1; } @@ -1836,7 +1837,6 @@ fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len) default: /* Added to quiet gcc */ case overlapped_success: case overlapped_error: - case overlapped_fallback: keep_looping = false; break; } @@ -1849,92 +1849,51 @@ fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len) ssize_t __stdcall __attribute__ ((regparm (3))) fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len) { - DWORD nbytes; + size_t nbytes; if (has_ongoing_io ()) nbytes = (DWORD) -1; else { - int last_errno = get_errno (); - bool keep_looping; - if (is_nonblocking () && max_atomic_write && len > max_atomic_write) - len = max_atomic_write; - do + size_t chunk; + if (!max_atomic_write || len < max_atomic_write) + chunk = len; + else if (is_nonblocking ()) + chunk = len = max_atomic_write; + else + chunk = max_atomic_write; + + nbytes = 0; + DWORD nbytes_now = 0; + /* Write to fd in smaller chunks, accumlating a total. + If there's an error, just return the accumulated total + unless the first write fails, in which case return value + from wait_overlapped(). */ + while (nbytes < len) { - bool res = WriteFile (get_output_handle (), ptr, len, &nbytes, + size_t left = len - nbytes; + size_t len1; + if (left > chunk) + len1 = chunk; + else + len1 = left; + bool res = WriteFile (get_output_handle (), ptr, len1, &nbytes_now, get_overlapped ()); - switch (wait_overlapped (res, true, &nbytes, is_nonblocking (), (size_t) len)) + switch (wait_overlapped (res, true, &nbytes_now, + is_nonblocking (), len1)) { - case overlapped_signal: - keep_looping = true; - break; - case overlapped_fallback: - set_errno (last_errno); /* Avoid setting a random EFBIG errno */ - nbytes = write_overlapped_fallback (ptr, len); - /* fall through intentionally */; - default: /* Added to quiet gcc */ case overlapped_success: + ptr = ((char *) ptr) + chunk; + nbytes += nbytes_now; + /* fall through intentionally */ + case overlapped_signal: + break; /* keep looping */ case overlapped_error: - keep_looping = false; + len = 0; /* terminate loop */ break; } } - while (keep_looping); - } - debug_printf ("returning %u", nbytes); - return nbytes; -} - -/* On XP (at least) the size of the buffer that can be used to write to a pipe - (pipes are currently the only thing using the overlapped methods) is - limited. This function is a fallback for when that problem is detected. - It writes to the pipe using smaller buffers but masks this behavior - to the caller. */ -ssize_t __stdcall __attribute__ ((regparm (3))) -fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t orig_len) -{ - size_t chunk; - /* So far, in testing, only the first if test has been necessary */ - if (orig_len > MAX_OVERLAPPED_WRITE_LEN) - chunk = MAX_OVERLAPPED_WRITE_LEN; - else if (orig_len > MIN_OVERLAPPED_WRITE_LEN) - chunk = MIN_OVERLAPPED_WRITE_LEN; - else - chunk = orig_len / 4; - ssize_t nbytes = 0; - DWORD nbytes_now = 0; - /* Write to fd in smaller chunks, accumlating a total. - If there's an error, just return the accumulated total - unless the first write fails, in which case return value - from wait_overlapped(). */ - while ((size_t) nbytes < orig_len) - { - size_t left = orig_len - nbytes; - size_t len; - if (left > chunk) - len = chunk; - else - len = left; - bool res = WriteFile (get_output_handle (), ptr, len, &nbytes_now, - get_overlapped ()); - /* The nonblocking case is not going to be used currently and may - eventually disappear. */ - switch (wait_overlapped (res, true, &nbytes_now, - left <= chunk ? is_nonblocking () : false, - (size_t) len)) - { - case overlapped_success: - nbytes += nbytes_now; - /* fall through intentionally */ - case overlapped_signal: - break; /* keep looping */ - case overlapped_error: - case overlapped_fallback: /* XXX Could make this more adaptive - if needed */ - orig_len = 0; /* terminate loop */ - break; - } + if (!nbytes) + nbytes = nbytes_now; } - if (!nbytes) - nbytes = nbytes_now; return nbytes; } diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index ee08e59..ffe8ee1 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -29,7 +29,7 @@ details. */ Using this blocksize in read/write calls in the application results in a much better performance than using smaller values. */ #define PREFERRED_IO_BLKSIZE ((blksize_t) 65536) -#define DEFAULT_PIPEBUFSIZE PREFERRED_IO_BLKSIZE +#define DEFAULT_PIPEBUFSIZE (31 * 1024 * 1024) extern const char *windows_device_names[]; extern struct __cygwin_perfile *perfile_table; @@ -570,8 +570,7 @@ protected: { overlapped_success = 0, overlapped_signal, - overlapped_error, - overlapped_fallback + overlapped_error }; bool io_pending; OVERLAPPED io_status; @@ -583,7 +582,6 @@ public: void __stdcall destroy_overlapped () __attribute__ ((regparm (1))); void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3))); ssize_t __stdcall write_overlapped (const void *ptr, size_t len) __attribute__ ((regparm (3))); - ssize_t __stdcall write_overlapped_fallback (const void *ptr, size_t orig_len) __attribute__ ((regparm (3))); OVERLAPPED *&get_overlapped () {return overlapped;} OVERLAPPED *get_overlapped_buffer () {return &io_status;} -- cgit v1.1