* 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.
This commit is contained in:
Christopher Faylor 2011-03-13 20:20:58 +00:00
parent 7a9064faa5
commit 9636c4262e
3 changed files with 56 additions and 83 deletions

View File

@ -1,3 +1,19 @@
2011-03-13 Christopher Faylor <me.cygwin2011@cgf.cx>
* 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 <me.cygwin2011@cgf.cx> 2011-03-09 Christopher Faylor <me.cygwin2011@cgf.cx>
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle
@ -10,7 +26,7 @@
(fhandler_base_overlapped::write_overlapped_fallback): Add some more (fhandler_base_overlapped::write_overlapped_fallback): Add some more
comments. comments.
2011-03-09 Christopher Faylor <me.cygwin@cgf.cx> 2011-03-09 Christopher Faylor <me.cygwin2011@cgf.cx>
* fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops! * fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops!
Accommodate change in arguments to wait_overlapped. Accommodate change in arguments to wait_overlapped.

View File

@ -1733,9 +1733,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
wait_return res; wait_return res;
DWORD err = GetLastError (); DWORD err = GetLastError ();
if (err == ERROR_NO_SYSTEM_RESOURCES) if (nonblocking)
res = overlapped_fallback;
else if (nonblocking)
{ {
if (!inres && err != ERROR_IO_PENDING) if (!inres && err != ERROR_IO_PENDING)
res = overlapped_error; res = overlapped_error;
@ -1806,6 +1804,9 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
else else
{ {
debug_printf ("err %u", err); debug_printf ("err %u", err);
HANDLE h = writing ? get_output_handle () : get_handle ();
CancelIo (h);
ResetEvent (get_overlapped ());
__seterrno_from_win_error (err); __seterrno_from_win_error (err);
*bytes = (DWORD) -1; *bytes = (DWORD) -1;
} }
@ -1836,7 +1837,6 @@ fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
default: /* Added to quiet gcc */ default: /* Added to quiet gcc */
case overlapped_success: case overlapped_success:
case overlapped_error: case overlapped_error:
case overlapped_fallback:
keep_looping = false; keep_looping = false;
break; break;
} }
@ -1849,92 +1849,51 @@ fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
ssize_t __stdcall __attribute__ ((regparm (3))) ssize_t __stdcall __attribute__ ((regparm (3)))
fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len) fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
{ {
DWORD nbytes; size_t nbytes;
if (has_ongoing_io ()) if (has_ongoing_io ())
nbytes = (DWORD) -1; nbytes = (DWORD) -1;
else else
{
int last_errno = get_errno ();
bool keep_looping;
if (is_nonblocking () && max_atomic_write && len > max_atomic_write)
len = max_atomic_write;
do
{
bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
get_overlapped ());
switch (wait_overlapped (res, true, &nbytes, is_nonblocking (), (size_t) len))
{
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:
case overlapped_error:
keep_looping = false;
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; size_t chunk;
/* So far, in testing, only the first if test has been necessary */ if (!max_atomic_write || len < max_atomic_write)
if (orig_len > MAX_OVERLAPPED_WRITE_LEN) chunk = len;
chunk = MAX_OVERLAPPED_WRITE_LEN; else if (is_nonblocking ())
else if (orig_len > MIN_OVERLAPPED_WRITE_LEN) chunk = len = max_atomic_write;
chunk = MIN_OVERLAPPED_WRITE_LEN;
else else
chunk = orig_len / 4; chunk = max_atomic_write;
ssize_t nbytes = 0;
nbytes = 0;
DWORD nbytes_now = 0; DWORD nbytes_now = 0;
/* Write to fd in smaller chunks, accumlating a total. /* Write to fd in smaller chunks, accumlating a total.
If there's an error, just return the accumulated total If there's an error, just return the accumulated total
unless the first write fails, in which case return value unless the first write fails, in which case return value
from wait_overlapped(). */ from wait_overlapped(). */
while ((size_t) nbytes < orig_len) while (nbytes < len)
{ {
size_t left = orig_len - nbytes; size_t left = len - nbytes;
size_t len; size_t len1;
if (left > chunk) if (left > chunk)
len = chunk; len1 = chunk;
else else
len = left; len1 = left;
bool res = WriteFile (get_output_handle (), ptr, len, &nbytes_now, bool res = WriteFile (get_output_handle (), ptr, len1, &nbytes_now,
get_overlapped ()); get_overlapped ());
/* The nonblocking case is not going to be used currently and may
eventually disappear. */
switch (wait_overlapped (res, true, &nbytes_now, switch (wait_overlapped (res, true, &nbytes_now,
left <= chunk ? is_nonblocking () : false, is_nonblocking (), len1))
(size_t) len))
{ {
case overlapped_success: case overlapped_success:
ptr = ((char *) ptr) + chunk;
nbytes += nbytes_now; nbytes += nbytes_now;
/* fall through intentionally */ /* fall through intentionally */
case overlapped_signal: case overlapped_signal:
break; /* keep looping */ break; /* keep looping */
case overlapped_error: case overlapped_error:
case overlapped_fallback: /* XXX Could make this more adaptive len = 0; /* terminate loop */
if needed */
orig_len = 0; /* terminate loop */
break; break;
} }
} }
if (!nbytes) if (!nbytes)
nbytes = nbytes_now; nbytes = nbytes_now;
}
return nbytes; return nbytes;
} }

View File

@ -29,7 +29,7 @@ details. */
Using this blocksize in read/write calls in the application results Using this blocksize in read/write calls in the application results
in a much better performance than using smaller values. */ in a much better performance than using smaller values. */
#define PREFERRED_IO_BLKSIZE ((blksize_t) 65536) #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 const char *windows_device_names[];
extern struct __cygwin_perfile *perfile_table; extern struct __cygwin_perfile *perfile_table;
@ -570,8 +570,7 @@ protected:
{ {
overlapped_success = 0, overlapped_success = 0,
overlapped_signal, overlapped_signal,
overlapped_error, overlapped_error
overlapped_fallback
}; };
bool io_pending; bool io_pending;
OVERLAPPED io_status; OVERLAPPED io_status;
@ -583,7 +582,6 @@ public:
void __stdcall destroy_overlapped () __attribute__ ((regparm (1))); void __stdcall destroy_overlapped () __attribute__ ((regparm (1)));
void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3))); 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 (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))); __attribute__ ((regparm (3)));
OVERLAPPED *&get_overlapped () {return overlapped;} OVERLAPPED *&get_overlapped () {return overlapped;}
OVERLAPPED *get_overlapped_buffer () {return &io_status;} OVERLAPPED *get_overlapped_buffer () {return &io_status;}