less: move "retry-on-EAGAIN" logic closer to read ops

This makes "G" (goto end of input) command work as well as
/search_for_nonexistent_string: both will read to EOF now
even from somewhat slow input (such as kernel's "git log").

function                                             old     new   delta
ndelay_on                                             35      43      +8
ndelay_off                                            35      43      +8
read_lines                                           695     691      -4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 16/-4)              Total: 12 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2014-09-22 21:14:02 +02:00
parent 15943c886d
commit d6e7672545
3 changed files with 29 additions and 32 deletions

View File

@ -390,8 +390,8 @@ const char *bb_basename(const char *name) FAST_FUNC;
char *last_char_is(const char *s, int c) FAST_FUNC;
const char* endofname(const char *name) FAST_FUNC;
void ndelay_on(int fd) FAST_FUNC;
void ndelay_off(int fd) FAST_FUNC;
int ndelay_on(int fd) FAST_FUNC;
int ndelay_off(int fd) FAST_FUNC;
void close_on_exec_on(int fd) FAST_FUNC;
void xdup2(int, int) FAST_FUNC;
void xmove_fd(int, int) FAST_FUNC;

View File

@ -25,20 +25,22 @@
#include "libbb.h"
/* Turn on nonblocking I/O on a fd */
void FAST_FUNC ndelay_on(int fd)
int FAST_FUNC ndelay_on(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (flags & O_NONBLOCK)
return;
return flags;
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
return flags;
}
void FAST_FUNC ndelay_off(int fd)
int FAST_FUNC ndelay_off(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (!(flags & O_NONBLOCK))
return;
return flags;
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
return flags;
}
void FAST_FUNC close_on_exec_on(int fd)

View File

@ -414,10 +414,10 @@ static void read_lines(void)
char *current_line, *p;
int w = width;
char last_terminated = terminated;
time_t last_time = 0;
int retry_EAGAIN = 2;
#if ENABLE_FEATURE_LESS_REGEXP
unsigned old_max_fline = max_fline;
time_t last_time = 0;
int had_progress = 2;
#endif
/* (careful: max_fline can be -1) */
@ -427,8 +427,6 @@ static void read_lines(void)
if (option_mask32 & FLAG_N)
w -= 8;
IF_FEATURE_LESS_REGEXP(again0:)
p = current_line = ((char*)xmalloc(w + 4)) + 4;
max_fline += last_terminated;
if (!last_terminated) {
@ -448,15 +446,29 @@ static void read_lines(void)
char c;
/* if no unprocessed chars left, eat more */
if (readpos >= readeof) {
errno = 0;
ndelay_on(0);
eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
ndelay_off(0);
int flags = ndelay_on(0);
while (1) {
time_t t;
errno = 0;
eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
if (errno != EAGAIN)
break;
t = time(NULL);
if (t != last_time) {
last_time = t;
if (--retry_EAGAIN < 0)
break;
}
sched_yield();
}
fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
readpos = 0;
readeof = eof_error;
if (eof_error <= 0)
goto reached_eof;
IF_FEATURE_LESS_REGEXP(had_progress = 1;)
retry_EAGAIN = 1;
}
c = readbuf[readpos];
/* backspace? [needed for manpages] */
@ -534,24 +546,7 @@ static void read_lines(void)
#endif
}
if (eof_error <= 0) {
#if !ENABLE_FEATURE_LESS_REGEXP
break;
#else
if (wanted_match < num_matches) {
break;
} /* else: goto_match() called us */
if (errno == EAGAIN) {
time_t t = time(NULL);
if (t != last_time) {
last_time = t;
if (--had_progress < 0)
break;
}
sched_yield();
goto again0;
}
break;
#endif
}
max_fline++;
current_line = ((char*)xmalloc(w + 4)) + 4;