* errno.cc (errmap): Change mapping of NO_SYSTEM_RESOURCES to EFBIG.
* fhandler.cc (MAX_OVERLAPPED_WRITE_LEN): New constant. (MIN_OVERLAPPED_WRITE_LEN): Ditto. (fhandler_base_overlapped::close): Accommodate change in arguments to wait_overlapped. (fhandler_base_overlapped::setup_overlapped): Add __stdcall and regparm modifiers. (fhandler_base_overlapped::destroy_overlapped): Ditto. (fhandler_base_overlapped::has_ongoing_io): Ditto. (fhandler_base_overlapped::wait_overlapped): Modify to return an enum returning various states. Accept nonblocking parameter. (fhandler_base_overlapped::read_overlapped): Add __stdcall and regparm modifiers. Rework to attempt to be smarter about reacting to states returned by wait_overlapped. (fhandler_base_overlapped::write_overlapped): Ditto. Add fallback option for when wait_overlapped detects that smaller chunks must be written. (fhandler_base_overlapped::write_overlapped_fallback): Ditto. * fhandler.h (DEFAULT_PIPEBUFSIZE): Move definition here from pipe.cc. (fhandler_base::has_ongoing_io): Define with __stdcall and regparm modifiers. (fhandler_base_overlapped::wait_return): New enum. (fhandler_base_overlapped::max_atomic_write): New variable. (fhandler_base_overlapped:: wait_overlapped): Accommodate changes mentioned above to arguments and modifiers. (fhandler_base_overlapped::setup_overlapped): Ditto for modifiers. (fhandler_base_overlapped::read_overlapped): Ditto. (fhandler_base_overlapped::write_overlapped): Ditto. (fhandler_base_overlapped::destroy_overlapped): Ditto. (fhandler_base_overlapped::has_ongoing_io): Ditto. (fhandler_base_overlapped::fhandler_base_overlapped): Zero max_atomic_write. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Set max_atomic_write to the size of the DEFAULT_PIPEBUFSIZE. (fhandler_fifo::wait): Accommodate change in arguments to wait_overlapped. * pipe.cc (fhandler_pipe::fhandler_pipe): Set max_atomic_write to the size of the DEFAULT_PIPEBUFSIZE. (fhandler_pipe::create_selectable): Allow minimum size of DEFAULT_PIPEBUFSIZE. (DEFAULT_PIPEBUFSIZE): Delete here, move to fhandler.h.
This commit is contained in:
parent
e7b5eaaac9
commit
779ece3ce0
|
@ -1,3 +1,46 @@
|
|||
2011-03-09 Christopher Faylor <me+cygwin@cgf.cx>
|
||||
|
||||
* errno.cc (errmap): Change mapping of NO_SYSTEM_RESOURCES to EFBIG.
|
||||
* fhandler.cc (MAX_OVERLAPPED_WRITE_LEN): New constant.
|
||||
(MIN_OVERLAPPED_WRITE_LEN): Ditto.
|
||||
(fhandler_base_overlapped::close): Accommodate change in arguments to
|
||||
wait_overlapped.
|
||||
(fhandler_base_overlapped::setup_overlapped): Add __stdcall and regparm
|
||||
modifiers.
|
||||
(fhandler_base_overlapped::destroy_overlapped): Ditto.
|
||||
(fhandler_base_overlapped::has_ongoing_io): Ditto.
|
||||
(fhandler_base_overlapped::wait_overlapped): Modify to return an enum
|
||||
returning various states. Accept nonblocking parameter.
|
||||
(fhandler_base_overlapped::read_overlapped): Add __stdcall and regparm
|
||||
modifiers. Rework to attempt to be smarter about reacting to states
|
||||
returned by wait_overlapped.
|
||||
(fhandler_base_overlapped::write_overlapped): Ditto. Add fallback
|
||||
option for when wait_overlapped detects that smaller chunks must be
|
||||
written.
|
||||
(fhandler_base_overlapped::write_overlapped_fallback): Ditto.
|
||||
* fhandler.h (DEFAULT_PIPEBUFSIZE): Move definition here from pipe.cc.
|
||||
(fhandler_base::has_ongoing_io): Define with __stdcall and regparm
|
||||
modifiers.
|
||||
(fhandler_base_overlapped::wait_return): New enum.
|
||||
(fhandler_base_overlapped::max_atomic_write): New variable.
|
||||
(fhandler_base_overlapped:: wait_overlapped): Accommodate changes
|
||||
mentioned above to arguments and modifiers.
|
||||
(fhandler_base_overlapped::setup_overlapped): Ditto for modifiers.
|
||||
(fhandler_base_overlapped::read_overlapped): Ditto.
|
||||
(fhandler_base_overlapped::write_overlapped): Ditto.
|
||||
(fhandler_base_overlapped::destroy_overlapped): Ditto.
|
||||
(fhandler_base_overlapped::has_ongoing_io): Ditto.
|
||||
(fhandler_base_overlapped::fhandler_base_overlapped): Zero
|
||||
max_atomic_write.
|
||||
* fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Set max_atomic_write
|
||||
to the size of the DEFAULT_PIPEBUFSIZE.
|
||||
(fhandler_fifo::wait): Accommodate change in arguments to
|
||||
wait_overlapped.
|
||||
* pipe.cc (fhandler_pipe::fhandler_pipe): Set max_atomic_write to the
|
||||
size of the DEFAULT_PIPEBUFSIZE.
|
||||
(fhandler_pipe::create_selectable): Allow minimum size of DEFAULT_PIPEBUFSIZE.
|
||||
(DEFAULT_PIPEBUFSIZE): Delete here, move to fhandler.h.
|
||||
|
||||
2011-03-08 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* security.cc: Fix copyright dates.
|
||||
|
|
|
@ -118,7 +118,7 @@ static NO_COPY struct
|
|||
X (NO_MORE_SEARCH_HANDLES, ENFILE),
|
||||
X (NO_PROC_SLOTS, EAGAIN),
|
||||
X (NO_SIGNAL_SENT, EIO),
|
||||
X (NO_SYSTEM_RESOURCES, EAGAIN),
|
||||
X (NO_SYSTEM_RESOURCES, EFBIG),
|
||||
X (NO_TOKEN, EINVAL),
|
||||
X (OPEN_FAILED, EIO),
|
||||
X (OPEN_FILES, EAGAIN),
|
||||
|
|
|
@ -29,6 +29,9 @@ details. */
|
|||
#include "cygtls.h"
|
||||
#include "sigproc.h"
|
||||
|
||||
#define MAX_OVERLAPPED_WRITE_LEN (64 * 1024 * 1024)
|
||||
#define MIN_OVERLAPPED_WRITE_LEN (1 * 1024 * 1024)
|
||||
|
||||
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
|
||||
|
||||
struct __cygwin_perfile *perfile_table;
|
||||
|
@ -1056,8 +1059,7 @@ fhandler_base_overlapped::close ()
|
|||
if (is_nonblocking () && io_pending)
|
||||
{
|
||||
DWORD bytes;
|
||||
set_nonblocking (false);
|
||||
wait_overlapped (1, !!(get_access () & GENERIC_WRITE), &bytes);
|
||||
wait_overlapped (1, !!(get_access () & GENERIC_WRITE), &bytes, false);
|
||||
}
|
||||
destroy_overlapped ();
|
||||
return fhandler_base::close ();
|
||||
|
@ -1686,7 +1688,7 @@ fhandler_base::fpathconf (int v)
|
|||
|
||||
/* Overlapped I/O */
|
||||
|
||||
int
|
||||
int __stdcall __attribute__ ((regparm (1)))
|
||||
fhandler_base_overlapped::setup_overlapped ()
|
||||
{
|
||||
OVERLAPPED *ov = get_overlapped_buffer ();
|
||||
|
@ -1696,7 +1698,7 @@ fhandler_base_overlapped::setup_overlapped ()
|
|||
return ov->hEvent ? 0 : -1;
|
||||
}
|
||||
|
||||
void
|
||||
void __stdcall __attribute__ ((regparm (1)))
|
||||
fhandler_base_overlapped::destroy_overlapped ()
|
||||
{
|
||||
OVERLAPPED *ov = get_overlapped ();
|
||||
|
@ -1709,7 +1711,7 @@ fhandler_base_overlapped::destroy_overlapped ()
|
|||
get_overlapped () = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
bool __stdcall __attribute__ ((regparm (1)))
|
||||
fhandler_base_overlapped::has_ongoing_io ()
|
||||
{
|
||||
if (!io_pending)
|
||||
|
@ -1723,27 +1725,25 @@ fhandler_base_overlapped::has_ongoing_io ()
|
|||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
|
||||
fhandler_base_overlapped::wait_return __stdcall __attribute__ ((regparm (3)))
|
||||
fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, bool nonblocking, DWORD len)
|
||||
{
|
||||
if (!get_overlapped ())
|
||||
return inres;
|
||||
|
||||
int res = 0;
|
||||
return inres ? overlapped_success : overlapped_error;
|
||||
|
||||
DWORD err = GetLastError ();
|
||||
if (is_nonblocking ())
|
||||
if (err == ERROR_NO_SYSTEM_RESOURCES)
|
||||
return overlapped_fallback;
|
||||
|
||||
wait_return res = overlapped_error;
|
||||
if (nonblocking)
|
||||
{
|
||||
if (inres || err == ERROR_IO_PENDING)
|
||||
{
|
||||
io_pending = err == ERROR_IO_PENDING;
|
||||
if (writing && !inres)
|
||||
*bytes = len; /* This really isn't true but it seems like
|
||||
this is a corner-case for linux's
|
||||
non-blocking I/O implementation. How can
|
||||
you know how many bytes were written until
|
||||
the I/O operation really completes? */
|
||||
res = 1;
|
||||
*bytes = len;
|
||||
res = overlapped_success;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1768,9 +1768,11 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
|||
if (signalled)
|
||||
{
|
||||
debug_printf ("got a signal");
|
||||
set_errno (EINTR);
|
||||
if (!_my_tls.call_signal_handler ())
|
||||
set_errno (EINTR);
|
||||
else
|
||||
res = overlapped_signal;
|
||||
*bytes = (DWORD) -1;
|
||||
res = 0;
|
||||
err = 0;
|
||||
}
|
||||
else if (!wores)
|
||||
|
@ -1781,7 +1783,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
|||
else
|
||||
{
|
||||
debug_printf ("normal %s, %u bytes", writing ? "write" : "read", *bytes);
|
||||
res = 1;
|
||||
res = overlapped_success;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1793,14 +1795,13 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
|||
debug_printf ("err %u", err);
|
||||
__seterrno_from_win_error (err);
|
||||
*bytes = (DWORD) -1;
|
||||
res = 0;
|
||||
res = overlapped_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 1;
|
||||
*bytes = 0;
|
||||
err = 0;
|
||||
debug_printf ("EOF");
|
||||
*bytes = 0;
|
||||
res = overlapped_success;
|
||||
}
|
||||
|
||||
if (writing && (err == ERROR_NO_DATA || err == ERROR_BROKEN_PIPE))
|
||||
|
@ -1808,39 +1809,119 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
|||
return res;
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
void __stdcall __attribute__ ((regparm (3)))
|
||||
fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
|
||||
{
|
||||
DWORD nbytes;
|
||||
if (has_ongoing_io ())
|
||||
nbytes = (DWORD) -1;
|
||||
else
|
||||
while (1)
|
||||
{
|
||||
bool res = ReadFile (get_handle (), ptr, len, &nbytes,
|
||||
get_overlapped ());
|
||||
int wres = wait_overlapped (res, false, &nbytes);
|
||||
if (wres || !_my_tls.call_signal_handler ())
|
||||
break;
|
||||
}
|
||||
{
|
||||
bool keep_looping;
|
||||
do
|
||||
{
|
||||
bool res = ReadFile (get_handle (), ptr, len, &nbytes,
|
||||
get_overlapped ());
|
||||
switch (wait_overlapped (res, false, &nbytes, is_nonblocking ()))
|
||||
{
|
||||
case overlapped_signal:
|
||||
keep_looping = true;
|
||||
break;
|
||||
default: /* Added to quiet gcc */
|
||||
case overlapped_success:
|
||||
case overlapped_error:
|
||||
case overlapped_fallback:
|
||||
keep_looping = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (keep_looping);
|
||||
}
|
||||
len = (size_t) nbytes;
|
||||
}
|
||||
|
||||
ssize_t __stdcall
|
||||
ssize_t __stdcall __attribute__ ((regparm (3)))
|
||||
fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
|
||||
{
|
||||
DWORD nbytes;
|
||||
if (has_ongoing_io ())
|
||||
nbytes = (DWORD) -1;
|
||||
else
|
||||
while (1)
|
||||
{
|
||||
bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
|
||||
get_overlapped ());
|
||||
int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
|
||||
if (wres || !_my_tls.call_signal_handler ())
|
||||
break;
|
||||
}
|
||||
{
|
||||
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, (size_t) len))
|
||||
{
|
||||
case overlapped_fallback:
|
||||
nbytes = write_overlapped_fallback (ptr, len);
|
||||
/* fall through intentionally */;
|
||||
case overlapped_signal:
|
||||
keep_looping = true;
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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: /* Could make this more adaptive
|
||||
if needed */
|
||||
orig_len = 0; /* terminate loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nbytes)
|
||||
nbytes = nbytes_now;
|
||||
return nbytes;
|
||||
}
|
||||
|
|
|
@ -29,6 +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
|
||||
|
||||
extern const char *windows_device_names[];
|
||||
extern struct __cygwin_perfile *perfile_table;
|
||||
|
@ -397,7 +398,7 @@ public:
|
|||
bool issymlink () {return pc.issymlink ();}
|
||||
bool device_access_denied (int) __attribute__ ((regparm (2)));
|
||||
int fhaccess (int flags, bool) __attribute__ ((regparm (3)));
|
||||
virtual bool has_ongoing_io () {return false;}
|
||||
virtual bool __stdcall has_ongoing_io () __attribute__ ((regparm (1))) {return false;}
|
||||
};
|
||||
|
||||
class fhandler_mailslot : public fhandler_base
|
||||
|
@ -565,23 +566,33 @@ class fhandler_socket: public fhandler_base
|
|||
class fhandler_base_overlapped: public fhandler_base
|
||||
{
|
||||
protected:
|
||||
enum wait_return
|
||||
{
|
||||
overlapped_success = 0,
|
||||
overlapped_signal,
|
||||
overlapped_error,
|
||||
overlapped_fallback
|
||||
};
|
||||
bool io_pending;
|
||||
OVERLAPPED io_status;
|
||||
OVERLAPPED *overlapped;
|
||||
size_t max_atomic_write;
|
||||
public:
|
||||
int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3)));
|
||||
int setup_overlapped () __attribute__ ((regparm (1)));
|
||||
void destroy_overlapped () __attribute__ ((regparm (1)));
|
||||
wait_return __stdcall wait_overlapped (bool, bool, DWORD *, bool, DWORD = 0) __attribute__ ((regparm (3)));
|
||||
int __stdcall setup_overlapped () __attribute__ ((regparm (1)));
|
||||
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);
|
||||
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;}
|
||||
void set_overlapped (OVERLAPPED *ov) {overlapped = ov;}
|
||||
fhandler_base_overlapped (): io_pending (false), overlapped (NULL)
|
||||
fhandler_base_overlapped (): io_pending (false), overlapped (NULL), max_atomic_write (0)
|
||||
{
|
||||
memset (&io_status, 0, sizeof io_status);
|
||||
}
|
||||
bool has_ongoing_io ();
|
||||
bool __stdcall has_ongoing_io () __attribute__ ((regparm (1)));
|
||||
|
||||
void fixup_after_fork (HANDLE);
|
||||
void fixup_after_exec ();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
|
||||
|
||||
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
@ -24,6 +25,7 @@
|
|||
fhandler_fifo::fhandler_fifo ():
|
||||
fhandler_base_overlapped (), wait_state (fifo_unknown), dummy_client (NULL)
|
||||
{
|
||||
max_atomic_write = DEFAULT_PIPEBUFSIZE;
|
||||
need_fork_fixup (true);
|
||||
}
|
||||
|
||||
|
@ -188,7 +190,7 @@ fhandler_fifo::wait (bool iswrite)
|
|||
int res = ConnectNamedPipe (get_handle (), get_overlapped ());
|
||||
if (GetLastError () != ERROR_NO_DATA && GetLastError () != ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
res = wait_overlapped (res, iswrite, &dummy_bytes);
|
||||
res = wait_overlapped (res, iswrite, &dummy_bytes, false);
|
||||
if (!res)
|
||||
{
|
||||
if (get_errno () != EINTR)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* pipe.cc: pipe for Cygwin.
|
||||
|
||||
Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
2008, 2009, 2010 Hat, Inc.
|
||||
2008, 2009, 2010, 2011 Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
@ -26,6 +26,7 @@ details. */
|
|||
fhandler_pipe::fhandler_pipe ()
|
||||
: fhandler_base_overlapped (), popen_pid (0)
|
||||
{
|
||||
max_atomic_write = DEFAULT_PIPEBUFSIZE;
|
||||
need_fork_fixup (true);
|
||||
uninterruptible_io (true);
|
||||
}
|
||||
|
@ -217,8 +218,8 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
|
|||
r = w = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* Ensure that there is enough pipe buffer space for atomic writes. */
|
||||
if (psize < PIPE_BUF)
|
||||
psize = PIPE_BUF;
|
||||
if (psize < DEFAULT_PIPEBUFSIZE)
|
||||
psize = DEFAULT_PIPEBUFSIZE;
|
||||
|
||||
char pipename[MAX_PATH];
|
||||
const size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
|
||||
|
@ -373,8 +374,6 @@ fhandler_pipe::fstatvfs (struct statvfs *sfs)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#define DEFAULT_PIPEBUFSIZE 65536
|
||||
|
||||
extern "C" int
|
||||
pipe (int filedes[2])
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue