From 002f009941fc76b11b9dbe0d951b896a5d4cbf9b Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Fri, 24 Feb 2012 11:40:45 +1100 Subject: [PATCH] Remove timerfd usage and go back to timelist. timefd is using too much cpu and it is using up file descriptors. timelist is also more portable and now I have less code to maintain. Signed-off-by: Angus Salkeld --- check | 9 -- configure.ac | 7 +- include/os_base.h | 4 - lib/Makefile.am | 6 +- lib/loop_poll.c | 210 +------------------------------------------ lib/loop_timerlist.c | 6 ++ 6 files changed, 11 insertions(+), 231 deletions(-) diff --git a/check b/check index 6fd2882..17007c8 100755 --- a/check +++ b/check @@ -14,7 +14,6 @@ help_all() { echo " nosection Check without gcc __attribute__(section)" echo " noepoll Check using poll (not epoll)" echo " nogettime Check without gettime()" - echo " notimerfd Check without timerfd" echo " bsd Check with a bsd-like config" echo " mac Check with a mac/darwin-like config" echo " dist do make distcheck" @@ -96,11 +95,6 @@ check_sysv() { export CFLAGS=$ORIG_CFLAGS } -check_notimerfd() { - # no timerfd - check "ac_cv_func_timerfd_create=no ac_cv_header_sys_timerfd_h=no" -} - check_nogettime() { # no clock_gettime check "ac_cv_func_clock_gettime=no" @@ -286,9 +280,6 @@ case $command in dist) check_dist ;; - notimerfd) - check_notimerfd - ;; coverity) check_coverity ;; diff --git a/configure.ac b/configure.ac index 34b4a5a..53b7abf 100644 --- a/configure.ac +++ b/configure.ac @@ -118,7 +118,7 @@ AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([arpa/inet.h link.h fcntl.h inttypes.h limits.h netinet/in.h stdint.h \ dlfcn.h time.h sys/time.h stdlib.h string.h strings.h sys/types.h sys/stat.h \ - sys/param.h sys/socket.h sys/time.h sys/timerfd.h sys/poll.h sys/epoll.h sys/uio.h \ + sys/param.h sys/socket.h sys/time.h sys/poll.h sys/epoll.h sys/uio.h \ sys/sockio.h sys/un.h sys/resource.h syslog.h errno.h unistd.h sys/mman.h \ sys/sem.h sys/ipc.h sys/msg.h mqueue.h]) @@ -143,7 +143,7 @@ AC_FUNC_MMAP AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday localtime localtime_r \ memset munmap socket strchr strrchr strdup strerror strstr \ poll epoll_create epoll_create1 random rand getrlimit sysconf \ - pthread_spin_lock timerfd_create pthread_setschedparam \ + pthread_spin_lock pthread_setschedparam \ sched_get_priority_max sched_setscheduler]) AC_CONFIG_LIBOBJ_DIR(lib) @@ -435,9 +435,6 @@ if test "x${supports_posix_mq}" = xyes ; then fi AM_CONDITIONAL(HAVE_POSIX_MQ, [test "x${supports_posix_mq}" = xyes]) - -AM_CONDITIONAL(USE_TIMERFD, [test "x$ac_cv_func_timerfd_create" = xyes]) - # --- callsite sections --- if test "x${GCC}" = xyes; then AC_MSG_CHECKING([whether GCC supports __attribute__((section())]) diff --git a/include/os_base.h b/include/os_base.h index 9ee3804..1420fe5 100644 --- a/include/os_base.h +++ b/include/os_base.h @@ -103,10 +103,6 @@ #define HAVE_MONOTONIC_CLOCK 1 #endif /* have monotonic clock */ -#ifdef HAVE_TIMERFD_CREATE -#define HAVE_TIMERFD 1 -#endif /* HAVE_TIMERFD_CREATE */ - #ifdef HAVE_EPOLL_CREATE1 #define HAVE_EPOLL 1 #endif /* HAVE_EPOLL_CREATE */ diff --git a/lib/Makefile.am b/lib/Makefile.am index a83fb35..df4158f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -39,7 +39,7 @@ lib_LTLIBRARIES = libqb.la libqb_la_LDFLAGS = -version-info 10:1:10 source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \ - loop.c loop_poll.c loop_job.c \ + loop.c loop_poll.c loop_job.c loop_timerlist.c \ ipcc.c ipcs.c ipc_shm.c ipc_us.c \ log.c log_thread.c log_blackbox.c log_file.c \ log_syslog.c log_dcs.c log_format.c \ @@ -56,10 +56,6 @@ if HAVE_POSIX_MQ libqb_la_SOURCES+=ipc_posix_mq.c endif -if USE_TIMERFD -else -libqb_la_SOURCES+=loop_timerlist.c -endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libqb.pc diff --git a/lib/loop_poll.c b/lib/loop_poll.c index 5218c8e..3dda460 100644 --- a/lib/loop_poll.c +++ b/lib/loop_poll.c @@ -34,9 +34,6 @@ int epoll_create1(int flags); #include #endif /* HAVE_SYS_POLL_H */ #ifndef S_SPLINT_S -#ifdef HAVE_SYS_TIMERFD_H -#include -#endif /* HAVE_SYS_TIMERFD_H */ #endif /* S_SPLINT_S */ #include @@ -142,7 +139,7 @@ _poll_entry_check_generate_(struct qb_poll_entry *pe) } } -#if defined(HAVE_TIMERFD) || defined(HAVE_EPOLL) +#if defined(HAVE_EPOLL) static int32_t _poll_entry_from_handle_(struct qb_poll_source *s, uint64_t handle_in, struct qb_poll_entry **pe_pt) @@ -162,7 +159,7 @@ _poll_entry_from_handle_(struct qb_poll_source *s, *pe_pt = pe; return 0; } -#endif /* HAVE_TIMERFD or HAVE_EPOLL */ +#endif /* HAVE_EPOLL */ static void _poll_entry_mark_deleted_(struct qb_poll_entry *pe) @@ -678,209 +675,6 @@ qb_loop_poll_del(struct qb_loop * lp, int32_t fd) return -EBADF; } -#ifdef HAVE_TIMERFD -static int32_t -_qb_timer_add_to_jobs_(struct qb_loop *l, struct qb_poll_entry *pe) -{ - uint64_t expired = 0; - ssize_t bytes = 0; - - assert(pe->item.type == QB_LOOP_TIMER); - if (pe->ufd.revents == POLLIN) { - bytes = read(pe->ufd.fd, &expired, sizeof(expired)); - if (bytes != sizeof(expired)) { - qb_util_perror(LOG_WARNING, - "couldn't read from timer fd %zd", - bytes); - } - qb_loop_level_item_add(&l->level[pe->p], &pe->item); - } else { - qb_util_log(LOG_ERR, "timer revents: %d expected %d", - pe->ufd.revents, POLLIN); - } - close(pe->ufd.fd); - pe->ufd.fd = -1; - pe->state = QB_POLL_ENTRY_JOBLIST; - return 1; -} - -int32_t -qb_loop_timer_msec_duration_to_expire(struct qb_loop_source * timer_source) -{ - return -1; -} - -struct qb_loop_source * -qb_loop_timer_create(struct qb_loop *l) -{ - return NULL; -} - -void -qb_loop_timer_destroy(struct qb_loop *l) -{ -} - -int32_t -qb_loop_timer_add(struct qb_loop *lp, - enum qb_loop_priority p, - uint64_t nsec_duration, - void *data, - qb_loop_timer_dispatch_fn timer_fn, - qb_loop_timer_handle * timer_handle_out) -{ - struct qb_poll_entry *pe; - int32_t fd; - int32_t res; - int32_t size, new_size; - struct itimerspec its; - struct qb_loop *l = lp; - - if (l == NULL) { - l = qb_loop_default_get(); - } - if (l == NULL || timer_fn == NULL) { - qb_util_log(LOG_ERR, - "can't add a timer with either (l == NULL || timer_fn == NULL)"); - return -EINVAL; - } - fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (fd == -1) { - res = -errno; - qb_util_perror(LOG_ERR, "failed to create timer"); - return res; - } - - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - its.it_value.tv_sec = nsec_duration / QB_TIME_NS_IN_SEC; - its.it_value.tv_nsec = nsec_duration % QB_TIME_NS_IN_SEC; - - res = timerfd_settime(fd, 0, &its, NULL); - if (res == -1) { - res = -errno; - qb_util_perror(LOG_ERR, "failed to set time on timer"); - goto close_and_return; - } - - size = ((struct qb_poll_source *)l->fd_source)->poll_entry_count; - res = _poll_add_(l, p, fd, POLLIN, data, &pe); - if (res != 0) { - goto close_and_return; - } - new_size = ((struct qb_poll_source *)l->fd_source)->poll_entry_count; - if (new_size > size) { - qb_util_log(LOG_TRACE, "grown poll array to %d for timer %d", - new_size, fd); - } - pe->timer_dispatch_fn = timer_fn; - pe->item.type = QB_LOOP_TIMER; - pe->add_to_jobs = _qb_timer_add_to_jobs_; - - if (timer_handle_out) { - *timer_handle_out = (((uint64_t) (pe->check)) << 32) | pe->install_pos; - } - - return res; - -close_and_return: - close(fd); - return res; -} - -int32_t -qb_loop_timer_del(struct qb_loop * lp, qb_loop_timer_handle th) -{ - struct qb_poll_entry *pe; - struct qb_poll_source *s; - int32_t res; - struct qb_loop *l = lp; - - if (l == NULL) { - l = qb_loop_default_get(); - } - if (l == NULL || th == 0) { - return -EINVAL; - } - s = (struct qb_poll_source *)l->fd_source; - res = _poll_entry_from_handle_(s, th, &pe); - if (res != 0) { - return res; - } - - if (pe->item.type != QB_LOOP_TIMER) { - qb_util_log(LOG_WARNING, - "trying to delete timer but handle points to type:%d", - pe->item.type); - return -EINVAL; - } - if (pe->state == QB_POLL_ENTRY_DELETED) { - return 0; - } - if (pe->state == QB_POLL_ENTRY_JOBLIST) { - qb_loop_level_item_del(&l->level[pe->p], &pe->item); - qb_util_log(LOG_DEBUG, "deleting timer in JOBLIST"); - } - if (pe->state != QB_POLL_ENTRY_ACTIVE && - pe->state != QB_POLL_ENTRY_JOBLIST) { - qb_util_log(LOG_WARNING, "trying to delete timer with state:%d", - pe->state); - return -EINVAL; - } - if (pe->ufd.fd != -1) { -#ifdef HAVE_EPOLL - if (epoll_ctl(s->epollfd, EPOLL_CTL_DEL, pe->ufd.fd, NULL) == - -1) { - qb_util_perror(LOG_DEBUG, "epoll_ctl(del:%d)", - pe->ufd.fd); - } -#else - s->ufds[pe->install_pos].fd = -1; - s->ufds[pe->install_pos].events = 0; - s->ufds[pe->install_pos].revents = 0; -#endif /* HAVE_EPOLL */ - close(pe->ufd.fd); - } - _poll_entry_mark_deleted_(pe); - - return 0; -} - -uint64_t -qb_loop_timer_expire_time_get(struct qb_loop * lp, qb_loop_timer_handle th) -{ - struct qb_poll_entry *pe; - struct qb_poll_source *s; - int32_t res = 0; - struct itimerspec its; - struct qb_loop *l = lp; - - if (l == NULL) { - l = qb_loop_default_get(); - } - if (l == NULL || th == 0) { - return 0; - } - s = (struct qb_poll_source *)l->fd_source; - res = _poll_entry_from_handle_(s, th, &pe); - if (res != 0) { - return 0; - } - - if (timerfd_gettime(pe->ufd.fd, &its) == -1) { - return 0; - } - return (its.it_value.tv_sec * QB_TIME_NS_IN_SEC) + its.it_value.tv_nsec; -} - -#endif /* HAVE_TIMERFD */ - -int32_t -qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th) -{ - return (qb_loop_timer_expire_time_get(l, th) > 0); -} - static int32_t pipe_fds[2] = { -1, -1 }; struct qb_signal_source { diff --git a/lib/loop_timerlist.c b/lib/loop_timerlist.c index 0cadc18..722f29b 100644 --- a/lib/loop_timerlist.c +++ b/lib/loop_timerlist.c @@ -277,3 +277,9 @@ qb_loop_timer_expire_time_get(struct qb_loop * lp, qb_loop_timer_handle th) return timerlist_expire_time(&s->timerlist, t->timerlist_handle); } + +int32_t +qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th) +{ + return (qb_loop_timer_expire_time_get(l, th) > 0); +}