1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

epoll is fashionable.

Added the configuration option --enable-epoll. Use epoll instead of select.
This commit is contained in:
Witold Filipczyk 2006-12-31 19:05:43 +01:00 committed by Witold Filipczyk
parent 38b09e44c7
commit 87e10dd412
4 changed files with 148 additions and 0 deletions

View File

@ -194,6 +194,7 @@ AC_CHECK_HEADERS(stdint.h inttypes.h)
AC_CHECK_HEADERS(locale.h pwd.h)
AC_CHECK_HEADERS(termios.h)
AC_CHECK_HEADERS(sys/epoll.h, [HAVE_SYS_EPOLL_H=yes])
AC_CHECK_HEADERS(sys/un.h,
[CONFIG_INTERLINK=yes
@ -297,6 +298,7 @@ AC_HAVE_FUNCS(cygwin_conv_to_full_win32_path)
AC_CHECK_FUNCS(setenv putenv, HAVE_SETENV_OR_PUTENV=yes)
AC_CHECK_FUNCS(getuid, HAVE_GETUID=yes)
AC_CHECK_FUNCS(geteuid, HAVE_GETEUID=yes)
AC_CHECK_FUNCS(epoll_ctl, HAVE_EPOLL_CTL=yes)
dnl These aren't probably needed now, as they are commented in links.h.
dnl I've no idea about their historical background, but I keep them here
@ -1344,6 +1346,9 @@ EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary],
EL_ARG_ENABLE(CONFIG_UTF8, utf-8, [UTF-8],
[ --enable-utf-8 enable UTF-8 support])
EL_ARG_DEPEND(CONFIG_EPOLL, epoll, [HAVE_SYS_EPOLL_H:yes HAVE_EPOLL_CTL:yes], [epoll],
[ --enable-epoll enable epoll])
EL_LOG_CONFIG(FESTIVAL, [festival], [])
EL_LOG_CONFIG(FLITE, [flite], [])

View File

@ -15,6 +15,9 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
#endif
#include "elinks.h"
@ -56,6 +59,7 @@
#include "viewer/text/marks.h"
struct program program;
int epoll_fd;
static int ac;
static unsigned char **av;
@ -114,6 +118,15 @@ init(void)
festival.in = -1;
festival.out = -1;
#endif
#ifdef CONFIG_EPOLL
epoll_fd = epoll_create(1024);
if (epoll_fd == -1) {
program.retval = RET_EPOLL;
program.terminate = 1;
return;
}
#endif
init_osdep();
check_cwd();

View File

@ -10,6 +10,7 @@ enum retval {
RET_PING, /* --remote "ping()" found no running ELinkses */
RET_REMOTE, /* --remote failed to connect to a running ELinks */
RET_COMMAND, /* Used internally for exiting from cmdline commands */
RET_EPOLL, /* Failed to epoll_create */
};
struct program {
@ -19,6 +20,7 @@ struct program {
};
extern struct program program;
extern int epoll_fd;
void shrink_memory(int);

View File

@ -26,6 +26,10 @@
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
#endif
#include "elinks.h"
#include "intl/gettext/libintl.h"
@ -52,6 +56,9 @@ struct thread {
static struct thread threads[FD_SETSIZE];
#ifdef CONFIG_EPOLL
static struct epoll_event events[FD_SETSIZE];
#else
static fd_set w_read;
static fd_set w_write;
static fd_set w_error;
@ -60,6 +67,7 @@ static fd_set x_read;
static fd_set x_write;
static fd_set x_error;
#endif
static int w_max;
int
@ -136,6 +144,125 @@ get_handler(int fd, enum select_handler_type tp)
return NULL;
}
#ifdef CONFIG_EPOLL
void
set_handlers(int fd, select_handler_T read_func, select_handler_T write_func,
select_handler_T error_func, void *data)
{
threads[fd].read_func = read_func;
threads[fd].write_func = write_func;
threads[fd].error_func = error_func;
threads[fd].data = data;
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.data.fd = fd;
if (read_func) ev.events |= EPOLLIN;
if (write_func) ev.events |= EPOLLOUT;
if (error_func) ev.events |= EPOLLERR;
if (read_func || write_func || error_func) {
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev))
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
if (fd > w_max) w_max = fd;
} else {
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev);
if (w_max == fd) w_max--;
}
}
void
select_loop(void (*init)(void))
{
timeval_T last_time;
int select_errors = 0;
clear_signal_mask_and_handlers();
timeval_now(&last_time);
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
init();
check_bottom_halves();
while (!program.terminate) {
int n, i, has_timer, timeout;
timeval_T t;
check_signals();
check_timers(&last_time);
redraw_all_terminals();
if (program.terminate) break;
has_timer = get_next_timer_time(&t);
if (!has_timer) break;
critical_section = 1;
if (check_signals()) {
critical_section = 0;
continue;
}
if (has_timer) {
/* Be sure timeout is not negative. */
timeval_limit_to_zero_or_one(&t);
timeout = (int)timeval_to_milliseconds(&t);
} else {
timeout = -1;
}
n = epoll_wait(epoll_fd, events, w_max, timeout);
if (n < 0) {
/* The following calls (especially gettext)
* might change errno. */
const int errno_from_select = errno;
critical_section = 0;
uninstall_alarm();
if (errno_from_select != EINTR) {
ERROR(gettext("The call to %s failed: %d (%s)"),
"epoll_wait()", errno_from_select, (unsigned char *) strerror(errno_from_select));
if (++select_errors > 10) /* Infinite loop prevention. */
INTERNAL(gettext("%d epoll_wait() failures."),
select_errors);
}
continue;
}
select_errors = 0;
critical_section = 0;
uninstall_alarm();
check_signals();
/*printf("sel: %d\n", n);*/
check_timers(&last_time);
for (i = 0; i < n; i++) {
int fd = events[i].data.fd;
if ((events[i].events & EPOLLIN)
&& threads[fd].read_func) {
threads[fd].read_func(threads[fd].data);
check_bottom_halves();
}
if ((events[i].events & EPOLLOUT)
&& threads[fd].write_func) {
threads[fd].write_func(threads[fd].data);
check_bottom_halves();
}
if ((events[i].events & EPOLLERR)
&& threads[fd].error_func) {
threads[fd].error_func(threads[fd].data);
check_bottom_halves();
}
}
}
close(epoll_fd);
}
#else
void
set_handlers(int fd, select_handler_T read_func, select_handler_T write_func,
select_handler_T error_func, void *data)
@ -312,6 +439,7 @@ select_loop(void (*init)(void))
}
}
}
#endif /* CONFIG_EPOLL */
static int
can_read_or_write(int fd, int write)