ioloop.c revision 007d354a674fb3ddf49db160cf050cf61270a1a0
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/*
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop.c : I/O loop
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen Copyright (c) 2002 Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen Permission is hereby granted, free of charge, to any person obtaining
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen a copy of this software and associated documentation files (the
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "Software"), to deal in the Software without restriction, including
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen without limitation the rights to use, copy, modify, merge, publish,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen distribute, sublicense, and/or sell copies of the Software, and to
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen permit persons to whom the Software is furnished to do so, subject to
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen the following conditions:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen The above copyright notice and this permission notice shall be
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen included in all copies or substantial portions of the Software.
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
f9f30736bc6e4cf535085824e7e124506fe2dbbbTimo Sirainen IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen*/
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen#include "lib.h"
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen#include "ioloop-internal.h"
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen#undef timercmp
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen#define timercmp(tvp, uvp) \
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen ((tvp)->tv_sec > (uvp)->tv_sec || \
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen ((tvp)->tv_sec == (uvp)->tv_sec && \
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen (tvp)->tv_usec > (uvp)->tv_usec))
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainentime_t ioloop_time = 0;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainenstruct timeval ioloop_timeval;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstruct timezone ioloop_timezone;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstatic struct ioloop *current_ioloop = NULL;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstatic void update_highest_fd(struct ioloop *ioloop)
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen{
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen struct io *io;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen int max_highest_fd;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen max_highest_fd = ioloop->highest_fd-1;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen ioloop->highest_fd = -1;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen for (io = ioloop->ios; io != NULL; io = io->next) {
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen if (!io->destroyed && io->fd > ioloop->highest_fd) {
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen ioloop->highest_fd = io->fd;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen if (ioloop->highest_fd == max_highest_fd)
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen break;
e925f007930955f10fa8728509a44f7a53d2b13eTimo Sirainen }
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen }
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen}
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstruct io *io_add(int fd, int condition, io_callback_t *callback, void *context)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen{
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen struct io *io;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(fd >= 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(callback != NULL);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io = p_new(current_ioloop->pool, struct io, 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io->fd = fd;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io->condition = condition;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io->callback = callback;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen io->context = context;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (io->fd > current_ioloop->highest_fd)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen current_ioloop->highest_fd = io->fd;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen io_loop_handle_add(current_ioloop, io->fd, io->condition);
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen io->next = current_ioloop->ios;
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen current_ioloop->ios = io;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen return io;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid io_remove(struct io *io)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(io != NULL);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(io->fd >= 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(io->fd <= current_ioloop->highest_fd);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* notify the real I/O handler */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_loop_handle_remove(current_ioloop, io->fd, io->condition);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* check if we removed the highest fd */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (io->fd == current_ioloop->highest_fd)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen update_highest_fd(current_ioloop);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io->destroyed = TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen io->fd = -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid io_destroy(struct ioloop *ioloop, struct io **io_p)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct io *io = *io_p;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* remove from list */
da4376093d4e1b26b14ea1e945689fb7056fe0a0Timo Sirainen *io_p = io->next;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen p_free(ioloop->pool, io);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void timeout_list_insert(struct ioloop *ioloop, struct timeout *timeout)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct timeout **t;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct timeval *next_run;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen next_run = &timeout->next_run;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (timercmp(&(*t)->next_run, next_run))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next = *t;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen *t = timeout;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen if (tv_now == NULL) {
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen if (gettimeofday(&timeout->next_run, NULL) < 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_fatal("gettimeofday(): %m");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_sec = tv_now->tv_sec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_usec = tv_now->tv_usec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* we don't want microsecond accuracy or this function will be
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen called all the time - millisecond is more than enough */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen timeout->next_run.tv_usec -= timeout->next_run.tv_usec % 1000;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_sec += timeout->msecs/1000;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_usec += (timeout->msecs%1000)*1000;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (timeout->next_run.tv_usec > 1000000) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout->next_run.tv_sec++;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout->next_run.tv_usec -= 1000000;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenstruct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback,
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen void *context)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen struct timeout *timeout;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout = p_new(current_ioloop->pool, struct timeout, 1);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout->msecs = msecs;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout->callback = callback;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout->context = context;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout_update_next(timeout, current_ioloop->running ?
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen NULL : &ioloop_timeval);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout_list_insert(current_ioloop, timeout);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return timeout;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainenvoid timeout_remove(struct timeout *timeout)
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(timeout != NULL);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen timeout->destroyed = TRUE;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenvoid timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen struct timeout *timeout = *timeout_p;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen *timeout_p = timeout->next;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen p_free(ioloop->pool, timeout);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint io_loop_get_wait_time(struct timeout *timeout, struct timeval *tv,
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen struct timeval *tv_now)
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen{
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen if (timeout == NULL) {
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen /* no timeouts. give it INT_MAX msecs. */
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen tv->tv_sec = INT_MAX / 1000;
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen tv->tv_usec = 0;
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen return INT_MAX;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (tv_now == NULL) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (gettimeofday(tv, NULL) < 0)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_fatal("gettimeofday(): %m");
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen } else {
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen tv->tv_sec = tv_now->tv_sec;
f9f30736bc6e4cf535085824e7e124506fe2dbbbTimo Sirainen tv->tv_usec = tv_now->tv_usec;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen tv->tv_sec = timeout->next_run.tv_sec - tv->tv_sec;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen tv->tv_usec = timeout->next_run.tv_usec - tv->tv_usec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (tv->tv_usec < 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen tv->tv_sec--;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen tv->tv_usec += 1000000;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (tv->tv_sec > 0 || (tv->tv_sec == 0 && tv->tv_usec > 0))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return tv->tv_sec*1000 + tv->tv_usec/1000;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* no need to calculate the times again with this timeout */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen tv->tv_sec = tv->tv_usec = 0;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen timeout->run_now = TRUE;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen return 0;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen}
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainenvoid io_loop_handle_timeouts(struct ioloop *ioloop)
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen{
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen struct timeout *t, **t_p;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen struct timeval tv;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int t_id;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_fatal("gettimeofday(): %m");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop_time = ioloop_timeval.tv_sec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
57dd2621d4230bc2e06c69a4b9f8cf8f0ff2bc93Timo Sirainen t_p = &ioloop->timeouts;
57dd2621d4230bc2e06c69a4b9f8cf8f0ff2bc93Timo Sirainen for (t = ioloop->timeouts; t != NULL; t = *t_p) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch if (t->destroyed) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout_destroy(ioloop, t_p);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen continue;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen t_p = &t->next;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
40ad2c4902e9d83557f2e8a4bff3d98fea2c8aa1Timo Sirainen if (!t->run_now) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen io_loop_get_wait_time(t, &tv, &ioloop_timeval);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!t->run_now)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen t->run_now = FALSE;
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen timeout_update_next(t, &ioloop_timeval);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen t_id = t_push();
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen t->callback(t->context);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen if (t_pop() != t_id)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen i_panic("Leaked a t_pop() call!");
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainenvoid io_loop_run(struct ioloop *ioloop)
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen{
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen ioloop->running = TRUE;
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen while (ioloop->running)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen io_loop_handler_run(ioloop);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid io_loop_stop(struct ioloop *ioloop)
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainen{
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainen ioloop->running = FALSE;
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainen}
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainen
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainenvoid io_loop_set_running(struct ioloop *ioloop)
1ff03d2244dd08effadfecec365bec28793a1aa0Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop->running = TRUE;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen}
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainenint io_loop_is_running(struct ioloop *ioloop)
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen{
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen return ioloop->running;
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen}
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainenstruct ioloop *io_loop_create(pool_t pool)
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen{
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen struct ioloop *ioloop;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen /* initialize time */
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen i_fatal("gettimeofday(): %m");
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen ioloop_time = ioloop_timeval.tv_sec;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen ioloop = p_new(pool, struct ioloop, 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen pool_ref(pool);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop->pool = pool;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop->highest_fd = -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_loop_handler_init(ioloop);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ioloop->prev = current_ioloop;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen current_ioloop = ioloop;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return ioloop;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid io_loop_destroy(struct ioloop *ioloop)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen pool_t pool;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen while (ioloop->ios != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct io *io = ioloop->ios;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!io->destroyed) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_warning("I/O leak: %p (%d)",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (void *) io->callback, io->fd);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_remove(io);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_destroy(ioloop, &ioloop->ios);
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen while (ioloop->timeouts != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct timeout *to = ioloop->timeouts;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!to->destroyed) {
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen i_warning("Timeout leak: %p", (void *) to->callback);
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen timeout_remove(to);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen timeout_destroy(ioloop, &ioloop->timeouts);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_loop_handler_deinit(ioloop);
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* ->prev won't work unless loops are destroyed in create order */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(ioloop == current_ioloop);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen current_ioloop = current_ioloop->prev;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen pool = ioloop->pool;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen p_free(pool, ioloop);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen pool_unref(pool);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen