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 <asalkeld@redhat.com>
This commit is contained in:
Angus Salkeld 2012-02-24 11:40:45 +11:00
parent 4356fbf577
commit 002f009941
6 changed files with 11 additions and 231 deletions

9
check
View File

@ -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
;;

View File

@ -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())])

View File

@ -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 */

View File

@ -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

View File

@ -34,9 +34,6 @@ int epoll_create1(int flags);
#include <sys/poll.h>
#endif /* HAVE_SYS_POLL_H */
#ifndef S_SPLINT_S
#ifdef HAVE_SYS_TIMERFD_H
#include <sys/timerfd.h>
#endif /* HAVE_SYS_TIMERFD_H */
#endif /* S_SPLINT_S */
#include <signal.h>
@ -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 {

View File

@ -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);
}