50133: use read-ahead and lseek-rewind for efficient line-buffered input

master
Bart Schaefer 2 years ago
parent 007c7df74a
commit df0c783f4b

@ -1,5 +1,9 @@
2022-04-28 Bart Schaefer <schaefer@zsh.org>
* 50133 (Bart, PWS, Jun-ichi): Src/input.c, configure.ac: when
lseek(2) is available, use it to check for and rewind read-ahead
for more efficient line-buffered input.
* 50126: Etc/BUGS, Src/exec.c: Fix multios in current-shell "exec"
* 50101: Src/Modules/system.c: sysread -o with param matches doc

@ -217,12 +217,34 @@ shinbufrestore(void)
static int
shingetchar(void)
{
int nread;
int nread, rsize = isset(SHINSTDIN) ? 1 : SHINBUFSIZE;
if (shinbufptr < shinbufendptr)
return STOUC(*shinbufptr++);
shinbufreset();
#ifdef USE_LSEEK
if (rsize == 1 && lseek(SHIN, 0, SEEK_CUR) != (off_t)-1)
rsize = SHINBUFSIZE;
if (rsize > 1) {
do {
errno = 0;
nread = read(SHIN, shinbuffer, rsize);
} while (nread < 0 && errno == EINTR);
if (nread <= 0)
return -1;
if (isset(SHINSTDIN) &&
(shinbufendptr = memchr(shinbuffer, '\n', nread))) {
shinbufendptr++;
rsize = (shinbufendptr - shinbuffer);
if (nread > rsize &&
lseek(SHIN, -(nread - rsize), SEEK_CUR) < 0)
zerr("lseek(%d, %d): %e", SHIN, -(nread - rsize), errno);
} else
shinbufendptr = shinbuffer + nread;
return STOUC(*shinbufptr++);
}
#endif
for (;;) {
errno = 0;
nread = read(SHIN, shinbufendptr, 1);

@ -2209,6 +2209,65 @@ if test x$zsh_cv_sys_fifo = xyes; then
AC_DEFINE(HAVE_FIFOS)
fi
dnl -----------
dnl check that lseek() correctly reports seekability.
dnl -----------
AC_CACHE_CHECK(if lseek() correctly reports seekability,
zsh_cv_sys_lseek,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
int main() {
int pipefd[2], fd;
off_t ret;
char* tmpfile = "seekfiletest.tmp";
if ((fd = open(tmpfile, O_CREAT, S_IRUSR)) < 0) {
fprintf(stderr, "creating file failed\n");
return 1;
}
ret = lseek(fd, 0, SEEK_CUR);
close(fd);
unlink(tmpfile);
if (ret == (off_t)-1) {
fprintf(stderr, "lseek on regular file failed\n");
return 1;
}
if (pipe(pipefd) < 0) {
fprintf(stderr, "creating pipe failed\n");
return 1;
}
write(pipefd[1], "abcdefgh", 8);
ret = lseek(pipefd[0], 0, SEEK_CUR);
close(pipefd[0]);
close(pipefd[1]);
if (ret != (off_t)-1) {
fprintf(stderr, "lseek on pipe succeeded\n");
return 1;
}
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "creating UNIX domain socket failed\n");
return 1;
}
ret = lseek(fd, 0, SEEK_CUR);
close(fd);
if (ret != (off_t)-1) {
fprintf(stderr, "lseek on UNIX domain socket succeeded\n");
return 1;
}
return 0;
}
]])],[zsh_cv_sys_lseek=yes],[zsh_cv_sys_lseek=no],[zsh_cv_sys_lseek=yes])
])
AH_TEMPLATE([USE_LSEEK],
[Define to 1 if lseek() can be used for SHIN.])
if test x$zsh_cv_sys_lseek = xyes; then
AC_DEFINE(USE_LSEEK)
fi
dnl -----------
dnl test for whether link() works
dnl for instance, BeOS R4.51 doesn't support hard links yet

Loading…
Cancel
Save