diff --git a/legacy/ecore/configure.ac b/legacy/ecore/configure.ac index 8ce84fbaaf..81049af986 100644 --- a/legacy/ecore/configure.ac +++ b/legacy/ecore/configure.ac @@ -890,6 +890,9 @@ m4_ifdef([AC_PROG_OBJC], [ ]) AC_SUBST(cocoa_ldflags) +# check for epoll support +AC_CHECK_HEADERS([sys/epoll.h]) + # basic pthread support EFL_CHECK_PTHREAD([no], [have_pthread="yes"], [have_pthread="no"]) diff --git a/legacy/ecore/src/lib/ecore/ecore.c b/legacy/ecore/src/lib/ecore/ecore.c index 910e759deb..2e6b0c3887 100644 --- a/legacy/ecore/src/lib/ecore/ecore.c +++ b/legacy/ecore/src/lib/ecore/ecore.c @@ -121,6 +121,7 @@ ecore_init(void) _ecore_glib_init(); _ecore_job_init(); _ecore_loop_time = ecore_time_get(); + _ecore_main_loop_init(); #if HAVE_MALLINFO if (getenv("ECORE_MEM_STAT")) diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c index efa985d0df..2a6af3ac8e 100644 --- a/legacy/ecore/src/lib/ecore/ecore_main.c +++ b/legacy/ecore/src/lib/ecore/ecore_main.c @@ -52,6 +52,10 @@ #include "Ecore.h" #include "ecore_private.h" +#ifdef HAVE_SYS_EPOLL_H +# define HAVE_EPOLL +# include +#endif struct _Ecore_Fd_Handler { @@ -121,6 +125,114 @@ static int (*main_loop_select)(int , fd_set *, fd_set *, fd_set *, struct timeva static double t1 = 0.0; static double t2 = 0.0; +#ifdef HAVE_EPOLL +static int epoll_fd = -1; +#endif + +void _ecore_main_loop_init(void) +{ +#ifdef HAVE_EPOLL + epoll_fd = epoll_create(1); + if (epoll_fd < 0) + CRIT("Failed to create epoll fd!"); +#endif +} + +static inline int _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh) +{ + int events = 0; +#ifdef HAVE_EPOLL + if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN; + if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT; + if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR; +#endif + return events; +} + +static inline int _ecore_main_fdh_epoll_add(Ecore_Fd_Handler *fdh) +{ + int r = 0; +#ifdef HAVE_EPOLL + struct epoll_event ev; + + ev.events = _ecore_poll_events_from_fdh(fdh); + ev.data.ptr = fdh; + INF("adding poll on %d %08x", fdh->fd, ev.events); + r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fdh->fd, &ev); +#endif + return r; +} + +static inline void _ecore_main_fdh_epoll_del(Ecore_Fd_Handler *fdh) +{ +#ifdef HAVE_EPOLL + struct epoll_event ev; + INF("removing poll on %d", fdh->fd); + /* could get an EBADF if somebody closed the FD before removing it */ + if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fdh->fd, &ev) && + errno != EBADF) + { + ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno); + } +#endif +} + +static inline int _ecore_main_fdh_epoll_modify(Ecore_Fd_Handler *fdh) +{ + int r = 0; +#ifdef HAVE_EPOLL + struct epoll_event ev; + + ev.events = _ecore_poll_events_from_fdh(fdh); + ev.data.ptr = fdh; + INF("modifing epoll on %d to %08x", fdh->fd, ev.events); + r = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fdh->fd, &ev); +#endif + return r; +} + +#ifdef HAVE_EPOLL +static inline int _ecore_main_fdh_epoll_mark_active(void) +{ + const int num_epoll_fds = 10; + struct epoll_event ev[num_epoll_fds]; + int i, ret; + + ret = epoll_wait(epoll_fd, ev, num_epoll_fds, 0); + if (ret < 0) + { + if (errno == EINTR) return -1; + ERR("epoll_wait failed %d", errno); + return -1; + } + + for (i=0; idelete_me) + { + ERR("deleted fd in epoll"); + continue; + } + if (ev->events & EPOLLIN) + fdh->read_active = 1; + if (ev->events & EPOLLOUT) + fdh->write_active = 1; + if (ev->events & EPOLLERR) + fdh->error_active = 1; + } + + return 0; +} +#endif + /** * @defgroup Ecore_Main_Loop_Group Main Loop Functions * @@ -262,6 +374,12 @@ ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER); fdh->fd = fd; fdh->flags = flags; + if (0 > _ecore_main_fdh_epoll_add(fdh)) + { + ERR("Failed to add epoll fd %d!", fd); + free(fdh); + return NULL; + } fdh->read_active = 0; fdh->write_active = 0; fdh->error_active = 0; @@ -326,6 +444,7 @@ ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) } fd_handler->delete_me = 1; fd_handlers_delete_me = 1; + _ecore_main_fdh_epoll_del(fd_handler); return fd_handler->data; } @@ -425,6 +544,10 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_ return; } fd_handler->flags = flags; + if (0 > _ecore_main_fdh_epoll_modify(fd_handler)) + { + ERR("Failed to mod epoll fd %d!", fd_handler->fd); + } } void @@ -504,6 +627,7 @@ _ecore_main_select(double timeout) FD_ZERO(&exfds); /* call the prepare callback for all handlers */ +#ifndef HAVE_EPOLL EINA_INLIST_FOREACH(fd_handlers, fdh) { if (!fdh->delete_me && fdh->prep_func) @@ -534,6 +658,12 @@ _ecore_main_select(double timeout) } } } +#else /* HAVE_EPOLL */ + /* polling on the epoll fd will wake when an fd in the epoll set is active */ + FD_SET(epoll_fd, &rfds); + max_fd = epoll_fd; +#endif /* HAVE_EPOLL */ + if (_ecore_signal_count_get()) return -1; ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t); @@ -549,6 +679,9 @@ _ecore_main_select(double timeout) } if (ret > 0) { +#ifdef HAVE_EPOLL + _ecore_main_fdh_epoll_mark_active(); +#else /* HAVE_EPOLL */ EINA_INLIST_FOREACH(fd_handlers, fdh) if (!fdh->delete_me) { @@ -559,6 +692,7 @@ _ecore_main_select(double timeout) if (FD_ISSET(fdh->fd, &exfds)) fdh->error_active = 1; } +#endif /* HAVE_EPOLL */ _ecore_main_fd_handlers_cleanup(); #ifdef _WIN32 _ecore_main_win32_handlers_cleanup();