зеркало из https://github.com/github/ruby.git
io.c: IO.copy_stream uses poll on Linux
poll and ppoll have a superior API which doesn't require the kernel to scan a potentially large bitmap to find a high-numbered FD [ruby-core:35572]. So favor using poll in case IO.copy_stream encounters a non-blocking FD. We cannot reliably use poll on most OSes, because file types (e.g. FIFOs) which work with select may not work with poll. Fortunately, Linux uses a common notification mechanism between all select/poll/epoll variants, so all file types are equally supported between the notification mechanisms. Verified by watching strace on the following scripts: *** maygvl_copy_stream_wait_read *** require 'io/nonblock' r, w = IO.pipe r.nonblock = true IO.copy_stream(r, "/dev/null") *** nogvl_copy_stream_wait_write *** require 'io/nonblock' r, w = IO.pipe w.nonblock = true IO.copy_stream("/dev/zero", w) * io.c (nogvl_wait_for_single_fd): new function for Linux (maygvl_copy_stream_wait_read): Linux-specific version (nogvl_copy_stream_wait_write): use nogvl_wait_for_single_fd [ruby-core:70051] [Feature #11377] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51305 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
8754f619d5
Коммит
f7c3b6ff72
|
@ -1,3 +1,10 @@
|
|||
Tue Jul 21 05:20:21 2015 Eric Wong <e@80x24.org>
|
||||
|
||||
* io.c (nogvl_wait_for_single_fd): new function for Linux
|
||||
(maygvl_copy_stream_wait_read): Linux-specific version
|
||||
(nogvl_copy_stream_wait_write): use nogvl_wait_for_single_fd
|
||||
[ruby-core:70051] [Feature #11377]
|
||||
|
||||
Mon Jul 20 15:04:30 2015 Eric Wong <e@80x24.org>
|
||||
|
||||
* parse.y (parser_initialize): avoid redundant zero-ing
|
||||
|
|
50
io.c
50
io.c
|
@ -10087,6 +10087,49 @@ maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* non-Linux poll may not work on all FDs */
|
||||
#if defined(HAVE_POLL) && defined(__linux__)
|
||||
# define USE_POLL 1
|
||||
# define IOWAIT_SYSCALL "poll"
|
||||
#else
|
||||
# define IOWAIT_SYSCALL "select"
|
||||
# define USE_POLL 0
|
||||
#endif
|
||||
|
||||
#if USE_POLL
|
||||
static int
|
||||
nogvl_wait_for_single_fd(int fd, short events)
|
||||
{
|
||||
struct pollfd fds;
|
||||
|
||||
fds.fd = fd;
|
||||
fds.events = events;
|
||||
|
||||
return poll(&fds, 1, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if (has_gvl) {
|
||||
ret = rb_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN, NULL);
|
||||
}
|
||||
else {
|
||||
ret = nogvl_wait_for_single_fd(stp->src_fd, POLLIN);
|
||||
}
|
||||
} while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
|
||||
|
||||
if (ret == -1) {
|
||||
stp->syserr = "poll";
|
||||
stp->error_no = errno;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else /* !USE_POLL */
|
||||
static int
|
||||
maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
|
||||
{
|
||||
|
@ -10114,6 +10157,7 @@ maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* !USE_POLL */
|
||||
|
||||
static int
|
||||
nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
|
||||
|
@ -10121,13 +10165,17 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
|
|||
int ret;
|
||||
|
||||
do {
|
||||
#if USE_POLL
|
||||
ret = nogvl_wait_for_single_fd(stp->dst_fd, POLLOUT);
|
||||
#else
|
||||
rb_fd_zero(&stp->fds);
|
||||
rb_fd_set(stp->dst_fd, &stp->fds);
|
||||
ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
|
||||
#endif
|
||||
} while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
|
||||
|
||||
if (ret == -1) {
|
||||
stp->syserr = "select";
|
||||
stp->syserr = IOWAIT_SYSCALL;
|
||||
stp->error_no = errno;
|
||||
return -1;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче