* 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:
parent
7a9064faa5
commit
9636c4262e
@ -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.
|
||||||
|
@ -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 ();
|
size_t chunk;
|
||||||
bool keep_looping;
|
if (!max_atomic_write || len < max_atomic_write)
|
||||||
if (is_nonblocking () && max_atomic_write && len > max_atomic_write)
|
chunk = len;
|
||||||
len = max_atomic_write;
|
else if (is_nonblocking ())
|
||||||
do
|
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 ());
|
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:
|
case overlapped_success:
|
||||||
|
ptr = ((char *) ptr) + chunk;
|
||||||
|
nbytes += nbytes_now;
|
||||||
|
/* fall through intentionally */
|
||||||
|
case overlapped_signal:
|
||||||
|
break; /* keep looping */
|
||||||
case overlapped_error:
|
case overlapped_error:
|
||||||
keep_looping = false;
|
len = 0; /* terminate loop */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (keep_looping);
|
if (!nbytes)
|
||||||
|
nbytes = nbytes_now;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
@ -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;}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user