ioloop.c revision 64f5f4f0e0c80ea8dc6f06f59e447fdf488635d0
/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "llist.h"
#include "time-util.h"
#include "istream-private.h"
#include "ioloop-private.h"
#include <unistd.h>
time_t ioloop_time = 0;
struct timeval ioloop_timeval;
{
unsigned int initial_fd_count;
}
static struct io_file *
const char *source_filename,
unsigned int source_linenum,
{
}
if (fd != -1)
else {
/* we're adding an istream whose only way to get notified
is to call i_stream_set_input_pending() */
}
}
return io;
}
const char *source_filename,
unsigned int source_linenum,
{
}
unsigned int source_linenum,
{
}
{
else
/* if we got here from an I/O handler callback, make sure we
don't try to handle this one next. */
}
{
/* make sure the callback doesn't get called anymore.
kqueue code relies on this. */
}
else {
/* remove io before it's freed */
}
else
/* remove io from the ioloop before unreferencing the istream,
because a destroyed istream may automatically close the
fd. */
}
}
{
}
{
}
{
}
}
{
i_fatal("gettimeofday(): %m");
} else {
}
/* we don't want microsecond accuracy or this function will be
called all the time - millisecond is more than enough */
}
}
static struct timeout *
{
}
return timeout;
}
unsigned int source_linenum,
{
if (msecs > 0) {
/* start this timeout in the next run cycle */
} else {
/* trigger zero timeouts as soon as possible */
NULL : &ioloop_timeval);
}
return timeout;
}
struct timeout *
unsigned int source_linenum,
{
}
struct timeout *
const char *source_filename,
unsigned int source_linenum,
{
return timeout;
}
static struct timeout *
{
}
return new_to;
}
{
}
{
break;
}
}
}
}
static void ATTR_NULL(2)
{
return;
/* if we came here from io_loop_handle_timeouts(),
next_run must be larger than tv_now or we could go to
infinite loop. +1000 to get 1 ms further, another +1000 to
account for timeout_update_next()'s truncation. */
}
}
}
{
}
{
int ret;
i_fatal("gettimeofday(): %m");
}
}
return 0;
}
/* round wait times up to next millisecond */
return ret;
}
{
struct priorityq_item *item;
int msecs;
/* we need to see if there are pending IO waiting,
if there is, we set msecs = 0 to ensure they are
processed without delay */
/* no timeouts. use INT_MAX msecs for timeval and
return -1;
}
if (ioloop->io_pending_count > 0) {
i_fatal("gettimeofday(): %m");
msecs = 0;
} else {
}
/* update ioloop_timeval - this is meant for io_loop_handle_timeouts()'s
ioloop_wait_usecs calculation. normally after this we go to the
ioloop and after that we update ioloop_timeval immediately again. */
return msecs;
}
{
}
{
i_warning("Time moved backwards by %ld seconds.",
}
}
{
return;
}
}
{
struct priorityq_item *const *items;
unsigned int i, count;
for (i = 0; i < count; i++) {
}
}
static void io_loops_timeouts_update(long diff_secs)
{
}
{
struct io_wait_timer *timer;
long long diff =
}
{
struct priorityq_item *item;
i_fatal("gettimeofday(): %m");
/* Don't bother comparing usecs. */
/* time moved backwards */
io_loops_timeouts_update(-(long)(ioloop_time -
/* the callback may have slept, so check the time again. */
i_fatal("gettimeofday(): %m");
} else {
ioloop->next_max_time)) {
/* time moved forwards */
}
}
/* use tv_call to make sure we don't get to infinite loop in
case callbacks update ioloop_timeval. */
break;
/* remove timeout from queue */
} else {
/* update timeout's next_run and reposition it in the queue */
}
i_panic("Leaked a t_pop() call in timeout handler %p",
}
}
}
{
T_BEGIN {
} T_END;
}
{
}
i_panic("Leaked a t_pop() call in I/O handler %p",
}
}
{
/* recursive io_loop_run() isn't allowed for the same ioloop.
it can break backends. */
}
{
while (ioloop->io_pending_count > 0) {
do {
if (ioloop->io_pending_count == 0)
break;
}
}
{
}
{
}
{
}
{
}
{
}
void io_loop_time_refresh(void)
{
i_fatal("gettimeofday(): %m");
}
struct ioloop *io_loop_create(void)
{
/* initialize time */
i_fatal("gettimeofday(): %m");
return ioloop;
}
{
struct priorityq_item *item;
/* ->prev won't work unless loops are destroyed in create order */
i_warning("I/O leak: %p (%s:%u, fd %d)",
}
to->source_linenum);
}
to->source_linenum);
}
i_warning("IO wait timer leak: %s:%u",
}
}
{
}
static void io_switch_callbacks_free(void)
{
}
{
io_switch_callback_t *const *callbackp;
if (array_is_created(&io_switch_callbacks)) {
(*callbackp)(prev_ioloop);
}
}
{
if (!array_is_created(&io_switch_callbacks)) {
}
}
{
io_switch_callback_t *const *callbackp;
unsigned int idx;
return;
}
}
i_unreached();
}
{
struct ioloop_context *ctx;
return ctx;
}
{
}
{
return;
/* cur_ctx itself keeps a reference */
}
{
struct ioloop_context_callback cb;
}
{
struct ioloop_context_callback *cb;
/* simply mark it as deleted, since we could get
here from activate/deactivate loop */
return;
}
}
i_panic("io_loop_context_remove_callbacks() context not found");
}
static void
{
const struct ioloop_context_callback *cbs;
unsigned int i, count;
for (i = 0; i < count; ) {
i++;
else {
}
}
}
{
struct ioloop_context_callback *cb;
}
}
{
struct ioloop_context_callback *cb;
/* we just added this callback. don't deactivate it
before it gets first activated. */
} else {
}
}
}
{
}
{
return old_io;
/* reference before io_remove() */
}
/* update istream io after it was removed with io_remove() */
}
return &new_io_file->io;
}
{
return old_to;
return new_to;
}
{
}
{
}
{
return ioloop->ioloop_wait_usecs;
}
{
enum io_condition conditions = 0;
}
return conditions;
}
struct io_wait_timer *
{
struct io_wait_timer *timer;
return timer;
}
{
return timer;
}
{
}
{
}