diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-10-01 16:21:31 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-10-01 16:21:31 +0200 |
commit | f33606112a59de6965692840b47d9cb4b924fc97 (patch) | |
tree | 14645c554f821e686128f5754b09c9be10909e8e /src | |
parent | 5ece3e359c4b96d0f9bf1ce690223545f40f34b8 (diff) | |
download | vim-git-f33606112a59de6965692840b47d9cb4b924fc97.tar.gz |
patch 8.0.1170: using termdebug results in 100% CPU timev8.0.1170
Problem: Using termdebug results in 100% CPU time. (tomleb)
Solution: Use polling instead of select().
Diffstat (limited to 'src')
-rw-r--r-- | src/channel.c | 64 | ||||
-rw-r--r-- | src/os_unix.c | 16 | ||||
-rw-r--r-- | src/proto/channel.pro | 4 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 71 insertions, 15 deletions
diff --git a/src/channel.c b/src/channel.c index 49bab16d1..606c66a86 100644 --- a/src/channel.c +++ b/src/channel.c @@ -3960,6 +3960,8 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) free_job_options(&opt); } +# define KEEP_OPEN_TIME 20 /* msec */ + # if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) /* * Add open channels to the poll struct. @@ -3967,7 +3969,7 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) * The type of "fds" is hidden to avoid problems with the function proto. */ int -channel_poll_setup(int nfd_in, void *fds_in) +channel_poll_setup(int nfd_in, void *fds_in, int *towait) { int nfd = nfd_in; channel_T *channel; @@ -3982,10 +3984,21 @@ channel_poll_setup(int nfd_in, void *fds_in) if (ch_part->ch_fd != INVALID_FD) { - ch_part->ch_poll_idx = nfd; - fds[nfd].fd = ch_part->ch_fd; - fds[nfd].events = POLLIN; - nfd++; + if (channel->ch_keep_open) + { + /* For unknown reason poll() returns immediately for a + * keep-open channel. Instead of adding it to the fds add + * a short timeout and check, like polling. */ + if (*towait < 0 || *towait > KEEP_OPEN_TIME) + *towait = KEEP_OPEN_TIME; + } + else + { + ch_part->ch_poll_idx = nfd; + fds[nfd].fd = ch_part->ch_fd; + fds[nfd].events = POLLIN; + nfd++; + } } else channel->ch_part[part].ch_poll_idx = -1; @@ -4021,6 +4034,12 @@ channel_poll_check(int ret_in, void *fds_in) channel_read(channel, part, "channel_poll_check"); --ret; } + else if (channel->ch_part[part].ch_fd != INVALID_FD + && channel->ch_keep_open) + { + /* polling a keep-open channel */ + channel_read(channel, part, "channel_poll_check_keep_open"); + } } in_part = &channel->ch_part[PART_IN]; @@ -4037,11 +4056,17 @@ channel_poll_check(int ret_in, void *fds_in) # endif /* UNIX && !HAVE_SELECT */ # if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO) + /* * The "fd_set" type is hidden to avoid problems with the function proto. */ int -channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in) +channel_select_setup( + int maxfd_in, + void *rfds_in, + void *wfds_in, + struct timeval *tv, + struct timeval **tvp) { int maxfd = maxfd_in; channel_T *channel; @@ -4057,9 +4082,25 @@ channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in) if (fd != INVALID_FD) { - FD_SET((int)fd, rfds); - if (maxfd < (int)fd) - maxfd = (int)fd; + if (channel->ch_keep_open) + { + /* For unknown reason select() returns immediately for a + * keep-open channel. Instead of adding it to the rfds add + * a short timeout and check, like polling. */ + if (*tvp == NULL || tv->tv_sec > 0 + || tv->tv_usec > KEEP_OPEN_TIME * 1000) + { + *tvp = tv; + tv->tv_sec = 0; + tv->tv_usec = KEEP_OPEN_TIME * 1000; + } + } + else + { + FD_SET((int)fd, rfds); + if (maxfd < (int)fd) + maxfd = (int)fd; + } } } } @@ -4094,6 +4135,11 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in) FD_CLR(fd, rfds); --ret; } + else if (fd != INVALID_FD && channel->ch_keep_open) + { + /* polling a keep-open channel */ + channel_read(channel, part, "channel_select_check_keep_open"); + } } in_part = &channel->ch_part[PART_IN]; diff --git a/src/os_unix.c b/src/os_unix.c index 3366efd1d..2a8e6ee43 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5330,6 +5330,9 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options) channel = add_channel(); if (channel == NULL) goto failed; + if (job->jv_tty_out != NULL) + ch_log(channel, "using pty %s on fd %d", + job->jv_tty_out, pty_master_fd); } BLOCK_SIGNALS(&curset); @@ -5702,6 +5705,9 @@ mch_create_pty_channel(job_T *job, jobopt_T *options) close(pty_master_fd); return FAIL; } + if (job->jv_tty_out != NULL) + ch_log(channel, "using pty %s on fd %d", + job->jv_tty_out, pty_master_fd); job->jv_channel = channel; /* ch_refcount was set by add_channel() */ channel->ch_keep_open = TRUE; @@ -5969,7 +5975,7 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted) } # endif #ifdef FEAT_JOB_CHANNEL - nfd = channel_poll_setup(nfd, &fds); + nfd = channel_poll_setup(nfd, &fds, &towait); #endif if (interrupted != NULL) *interrupted = FALSE; @@ -6021,7 +6027,8 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted) } # endif #ifdef FEAT_JOB_CHANNEL - if (ret > 0) + /* also call when ret == 0, we may be polling a keep-open channel */ + if (ret >= 0) ret = channel_poll_check(ret, &fds); #endif @@ -6097,7 +6104,7 @@ select_eintr: } # endif # ifdef FEAT_JOB_CHANNEL - maxfd = channel_select_setup(maxfd, &rfds, &wfds); + maxfd = channel_select_setup(maxfd, &rfds, &wfds, &tv, &tvp); # endif if (interrupted != NULL) *interrupted = FALSE; @@ -6183,7 +6190,8 @@ select_eintr: } # endif #ifdef FEAT_JOB_CHANNEL - if (ret > 0) + /* also call when ret == 0, we may be polling a keep-open channel */ + if (ret >= 0) ret = channel_select_check(ret, &rfds, &wfds); #endif diff --git a/src/proto/channel.pro b/src/proto/channel.pro index a3a4dc701..40742adad 100644 --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -40,9 +40,9 @@ void channel_set_nonblock(channel_T *channel, ch_part_T part); int channel_send(channel_T *channel, ch_part_T part, char_u *buf_arg, int len_arg, char *fun); void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval); void ch_raw_common(typval_T *argvars, typval_T *rettv, int eval); -int channel_poll_setup(int nfd_in, void *fds_in); +int channel_poll_setup(int nfd_in, void *fds_in, int *towait); int channel_poll_check(int ret_in, void *fds_in); -int channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in); +int channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in, struct timeval *tv, struct timeval **tvp); int channel_select_check(int ret_in, void *rfds_in, void *wfds_in); int channel_parse_messages(void); int channel_any_readahead(void); diff --git a/src/version.c b/src/version.c index 23859a117..d809ba978 100644 --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1170, +/**/ 1169, /**/ 1168, |