From: Timo Sirainen Date: Tue, 15 Nov 2016 10:21:56 +0000 (+0100) Subject: lib: Added io_wait_timer X-Git-Tag: 2.2.27~162 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4c8b67114485a33f107747bba8bff88fde8f315f;p=thirdparty%2Fdovecot%2Fcore.git lib: Added io_wait_timer This allows easier tracking of how much time the io_wait_timer has been spending on (multiple) ioloops. --- diff --git a/src/lib/ioloop-private.h b/src/lib/ioloop-private.h index 97d20749ee..a4b879f9c2 100644 --- a/src/lib/ioloop-private.h +++ b/src/lib/ioloop-private.h @@ -18,6 +18,7 @@ struct ioloop { struct io_file *next_io_file; struct priorityq *timeouts; ARRAY(struct timeout *) timeouts_new; + struct io_wait_timer *wait_timers; struct ioloop_handler_context *handler_context; struct ioloop_notify_handler_context *notify_handler_context; @@ -79,6 +80,15 @@ struct timeout { unsigned int one_shot:1; }; +struct io_wait_timer { + struct io_wait_timer *prev, *next; + const char *source_filename; + unsigned int source_linenum; + + struct ioloop *ioloop; + uint64_t usecs; +}; + struct ioloop_context_callback { io_callback_t *activate; io_callback_t *deactivate; diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index 59a1219c09..a04b98765e 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -2,6 +2,7 @@ #include "lib.h" #include "array.h" +#include "llist.h" #include "time-util.h" #include "istream-private.h" #include "ioloop-private.h" @@ -499,10 +500,14 @@ static void io_loops_timeouts_update(long diff_secs) static void ioloop_add_wait_time(struct ioloop *ioloop) { + struct io_wait_timer *timer; long long diff = timeval_diff_usecs(&ioloop_timeval, &ioloop->wait_started); ioloop->ioloop_wait_usecs += diff; ioloop_global_wait_usecs += diff; + + for (timer = ioloop->wait_timers; timer != NULL; timer = timer->next) + timer->usecs += diff; } static void io_loop_handle_timeouts_real(struct ioloop *ioloop) @@ -740,6 +745,15 @@ void io_loop_destroy(struct ioloop **_ioloop) } priorityq_deinit(&ioloop->timeouts); + while (ioloop->wait_timers != NULL) { + struct io_wait_timer *timer = ioloop->wait_timers; + + i_warning("IO wait timer leak: %s:%u", + timer->source_filename, + timer->source_linenum); + io_wait_timer_remove(&timer); + } + if (ioloop->handler_context != NULL) io_loop_handler_deinit(ioloop); @@ -1002,3 +1016,42 @@ enum io_condition io_loop_find_fd_conditions(struct ioloop *ioloop, int fd) } return conditions; } + +#undef io_wait_timer_add +struct io_wait_timer * +io_wait_timer_add(const char *source_filename, unsigned int source_linenum) +{ + struct io_wait_timer *timer; + + timer = i_new(struct io_wait_timer, 1); + timer->ioloop = current_ioloop; + timer->source_filename = source_filename; + timer->source_linenum = source_linenum; + DLLIST_PREPEND(¤t_ioloop->wait_timers, timer); + return timer; +} + +struct io_wait_timer *io_wait_timer_move(struct io_wait_timer **_timer) +{ + struct io_wait_timer *timer = *_timer; + + *_timer = NULL; + DLLIST_REMOVE(&timer->ioloop->wait_timers, timer); + DLLIST_PREPEND(¤t_ioloop->wait_timers, timer); + timer->ioloop = current_ioloop; + return timer; +} + +void io_wait_timer_remove(struct io_wait_timer **_timer) +{ + struct io_wait_timer *timer = *_timer; + + *_timer = NULL; + DLLIST_REMOVE(&timer->ioloop->wait_timers, timer); + i_free(timer); +} + +uint64_t io_wait_timer_get_usecs(struct io_wait_timer *timer) +{ + return timer->usecs; +} diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index c33d841064..f42e7286b0 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -183,6 +183,18 @@ struct ioloop_context *io_loop_get_current_context(struct ioloop *ioloop); Returns fd on success, -1 on error. */ int io_loop_extract_notify_fd(struct ioloop *ioloop); +/* IO wait timers can be used to track how much time the io_wait_timer has + spent on waiting in its ioloops. This is similar to + io_loop_get_wait_usecs(), but it's easier to use when the wait time needs + to be tracked across multiple ioloops. */ +struct io_wait_timer * +io_wait_timer_add(const char *source_filename, unsigned int source_linenum); +#define io_wait_timer_add() \ + io_wait_timer_add(__FILE__, __LINE__) +struct io_wait_timer *io_wait_timer_move(struct io_wait_timer **timer); +void io_wait_timer_remove(struct io_wait_timer **timer); +uint64_t io_wait_timer_get_usecs(struct io_wait_timer *timer); + /* Move the given I/O into the current I/O loop if it's not already there. New I/O is returned, while the old one is freed. */ struct io *io_loop_move_io(struct io **io);