ioloop.c revision c0435c854a0e7246373b9752d163095cc4fbe985
cd348e325366620fe047edcc849e3c9424828599Peter Bray/*
cd348e325366620fe047edcc849e3c9424828599Peter Bray ioloop.c : I/O loop
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco
cd348e325366620fe047edcc849e3c9424828599Peter Bray Copyright (c) 2002 Timo Sirainen
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal Permission is hereby granted, free of charge, to any person obtaining
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco a copy of this software and associated documentation files (the
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray "Software"), to deal in the Software without restriction, including
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray without limitation the rights to use, copy, modify, merge, publish,
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray distribute, sublicense, and/or sell copies of the Software, and to
d20bb899e2e6c692130af57903cb0f909e7bec2aGerbrand van Dieijen permit persons to whom the Software is furnished to do so, subject to
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco the following conditions:
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray The above copyright notice and this permission notice shall be
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray included in all copies or substantial portions of the Software.
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray*/
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal/* FIXME: inserting io is slow if there's lots of them. I should add a linked
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal list of priorities pointing to first item in the list with the priority. */
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco#include "lib.h"
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco#include "ioloop-internal.h"
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco#undef timercmp
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray#define timercmp(tvp, uvp) \
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray ((tvp)->tv_sec > (uvp)->tv_sec || \
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray ((tvp)->tv_sec == (uvp)->tv_sec && \
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray (tvp)->tv_usec > (uvp)->tv_usec))
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotaltime_t ioloop_time = 0;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotalstruct timeval ioloop_timeval;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Braystruct timezone ioloop_timezone;
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotalstatic struct ioloop *current_ioloop = NULL;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotalstatic void update_highest_fd(struct ioloop *ioloop)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal{
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal struct io *io;
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal int max_highest_fd;
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal max_highest_fd = ioloop->highest_fd-1;
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal ioloop->highest_fd = -1;
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal for (io = ioloop->ios; io != NULL; io = io->next) {
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal if (!io->destroyed && io->fd > ioloop->highest_fd) {
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal ioloop->highest_fd = io->fd;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal if (ioloop->highest_fd == max_highest_fd)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal break;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal }
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal }
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet}
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet
56c25decc0427c204cd35856e521ddf28337e75dLubos Koscostatic void io_list_insert(struct ioloop *ioloop, struct io *io)
56c25decc0427c204cd35856e521ddf28337e75dLubos Kosco{
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal struct io *prev, *next;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal prev = NULL;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal for (next = ioloop->ios; next != NULL; next = next->next) {
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal if (next->priority >= io->priority)
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal break;
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal prev = next;
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal }
3ba66fbb56ef22f183da783a1b2718280c357a4eStanislav Kozina
3ba66fbb56ef22f183da783a1b2718280c357a4eStanislav Kozina if (prev == NULL)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal ioloop->ios = io;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal else {
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco io->prev = prev;
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco prev->next = io;
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco }
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco if (next != NULL) {
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal io->next = next;
9132ad6a7ba5525fd1a6ccd4f4bcb497385c8597ralphmayr next->prev = io;
9132ad6a7ba5525fd1a6ccd4f4bcb497385c8597ralphmayr }
9132ad6a7ba5525fd1a6ccd4f4bcb497385c8597ralphmayr}
9132ad6a7ba5525fd1a6ccd4f4bcb497385c8597ralphmayr
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Braystruct io *io_add(int fd, int condition, IOFunc func, void *data)
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray{
c577d2f6c082eaff9af5bc997d12f3d3bcef537cPeter Bray return io_add_priority(fd, IO_PRIORITY_DEFAULT,
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray condition, func, data);
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco}
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
425278cfacbc73f1e955ab6016f206fc5ed93ccbVladimir Kotalstruct io *io_add_priority(int fd, int priority, int condition,
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal IOFunc func, void *context)
cd348e325366620fe047edcc849e3c9424828599Peter Bray{
3b0448fdd830b8d04c6a71511e5d26a4fc3b5b80Lubos Kosco struct io *io;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray i_assert(fd >= 0);
cd348e325366620fe047edcc849e3c9424828599Peter Bray i_assert(func != NULL);
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal io = p_new(current_ioloop->pool, struct io, 1);
43dac746513591adbd09bc4f417feb385f4fd87eVladimir Kotal io->fd = fd;
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco io->priority = priority;
3a4816d2417e1abe89a913616de36f200793bea3Vladimir Kotal io->condition = condition;
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco
610915d59310c9aba810740e858ba64c5e3e6a2fVladimir Kotal io->func = func;
527d116ec0f031818982101f4475298b930d515bVladimir Kotal io->context = context;
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco if (io->fd > current_ioloop->highest_fd)
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco current_ioloop->highest_fd = io->fd;
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco
fbf97ea1786d1e25add88bbfb91810170473bc9fLubos Kosco io_loop_handle_add(current_ioloop, io->fd, io->condition);
f21b682cd9b414738a4f5a38b56f6682e537e1d2Trond Norbye io_list_insert(current_ioloop, io);
3b0448fdd830b8d04c6a71511e5d26a4fc3b5b80Lubos Kosco
3b0448fdd830b8d04c6a71511e5d26a4fc3b5b80Lubos Kosco return io;
cd348e325366620fe047edcc849e3c9424828599Peter Bray}
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Brayvoid io_remove(struct io *io)
cd348e325366620fe047edcc849e3c9424828599Peter Bray{
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray i_assert(io != NULL);
cd348e325366620fe047edcc849e3c9424828599Peter Bray i_assert(io->fd >= 0);
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal i_assert(io->fd <= current_ioloop->highest_fd);
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal /* notify the real I/O handler */
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal io_loop_handle_remove(current_ioloop, io->fd, io->condition);
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal /* check if we removed the highest fd */
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco if (io->fd == current_ioloop->highest_fd)
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal update_highest_fd(current_ioloop);
c276b1ec9722ee95a86a4a381b39c5f405fc1cc4Vladimir Kotal
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco io->destroyed = TRUE;
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco io->fd = -1;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray}
5a0ed1213a40c9ab7c990b442b77455ee27bc799Vladimir Kotal
5a0ed1213a40c9ab7c990b442b77455ee27bc799Vladimir Kotalvoid io_destroy(struct ioloop *ioloop, struct io *io)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray{
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray /* remove from list */
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray if (io->prev == NULL)
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray ioloop->ios = io->next;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray else
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray io->prev->next = io->next;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray if (io->next != NULL)
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray io->next->prev = io->prev;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray p_free(ioloop->pool, io);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray}
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Braystatic void timeout_list_insert(struct ioloop *ioloop, struct timeout *timeout)
cd348e325366620fe047edcc849e3c9424828599Peter Bray{
cd348e325366620fe047edcc849e3c9424828599Peter Bray struct timeout **t;
cd348e325366620fe047edcc849e3c9424828599Peter Bray struct timeval *next_run;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray next_run = &timeout->next_run;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray if (timercmp(&(*t)->next_run, next_run))
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray break;
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco }
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco timeout->next = *t;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray *t = timeout;
5762c9f28c2246777be0e9d49cb29d9c0f49146dLubos Kosco}
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Brayinline static void
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Braytimeout_update_next(struct timeout *timeout, struct timeval *tv_now)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray{
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray if (tv_now == NULL)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray gettimeofday(&timeout->next_run, NULL);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray else {
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray timeout->next_run.tv_sec = tv_now->tv_sec;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray timeout->next_run.tv_usec = tv_now->tv_usec;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco }
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray /* we don't want microsecond accuracy or this function will be
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco called all the time - millisecond is more than enough */
c83dfde6b364917fa8ed28142d509a7c29a4da68Vladimir Kotal timeout->next_run.tv_usec /= 1000;
c83dfde6b364917fa8ed28142d509a7c29a4da68Vladimir Kotal timeout->next_run.tv_usec *= 1000;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout->next_run.tv_sec += timeout->msecs/1000;
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout->next_run.tv_usec += (timeout->msecs%1000)*1000;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray if (timeout->next_run.tv_usec > 1000000) {
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray timeout->next_run.tv_sec++;
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout->next_run.tv_usec -= 1000000;
cd348e325366620fe047edcc849e3c9424828599Peter Bray }
cd348e325366620fe047edcc849e3c9424828599Peter Bray}
cd348e325366620fe047edcc849e3c9424828599Peter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Braystruct timeout *timeout_add(int msecs, TimeoutFunc func, void *context)
cd348e325366620fe047edcc849e3c9424828599Peter Bray{
0b2998be561e7bf5e3479d686a5af36f712b0d9aVladimir Kotal struct timeout *timeout;
0b2998be561e7bf5e3479d686a5af36f712b0d9aVladimir Kotal
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout = p_new(current_ioloop->pool, struct timeout, 1);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray timeout->msecs = msecs;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray timeout->func = func;
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout->context = context;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray timeout_update_next(timeout, current_ioloop->running ?
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco NULL : &ioloop_timeval);
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco timeout_list_insert(current_ioloop, timeout);
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco return timeout;
d7c1415de39f4b07c85828f49cd1ee7a2a19eb9eLubos Kosco}
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Koscovoid timeout_remove(struct timeout *timeout)
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco{
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray i_assert(timeout != NULL);
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal timeout->destroyed = TRUE;
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal}
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotalvoid timeout_destroy(struct ioloop *ioloop, struct timeout *timeout)
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal{
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal struct timeout **t;
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal
bc5565fc58603964988b42b6aee40e246f35d94fVladimir Kotal for (t = &ioloop->timeouts; *t != NULL; t = &(*t)->next) {
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray if (*t == timeout)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray break;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray }
3aa0947feb67d3e8292d84776638be98dd97fdc3Lubos Kosco *t = timeout->next;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray p_free(ioloop->pool, timeout);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray}
cd348e325366620fe047edcc849e3c9424828599Peter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Brayint io_loop_get_wait_time(struct timeout *timeout, struct timeval *tv,
cd348e325366620fe047edcc849e3c9424828599Peter Bray struct timeval *tv_now)
cd348e325366620fe047edcc849e3c9424828599Peter Bray{
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray if (timeout == NULL)
cd348e325366620fe047edcc849e3c9424828599Peter Bray return INT_MAX;
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal
e9dbb478e3339d96ce4f0af5c6ab7e1d35ebb86dVladimir Kotal if (tv_now == NULL)
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal gettimeofday(tv, NULL);
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal else {
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal tv->tv_sec = tv_now->tv_sec;
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal tv->tv_usec = tv_now->tv_usec;
d961aa46ea0d50fed47802497e45226b1965b12dVladimir Kotal }
cd348e325366620fe047edcc849e3c9424828599Peter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray tv->tv_sec = timeout->next_run.tv_sec - tv->tv_sec;
cd348e325366620fe047edcc849e3c9424828599Peter Bray tv->tv_usec = timeout->next_run.tv_usec - tv->tv_usec;
cd348e325366620fe047edcc849e3c9424828599Peter Bray if (tv->tv_usec < 0) {
cd348e325366620fe047edcc849e3c9424828599Peter Bray tv->tv_sec--;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray tv->tv_usec += 1000000;
cd348e325366620fe047edcc849e3c9424828599Peter Bray }
56d93b0c761868f813ac0bc0b5bc21a7a9fefd89Vladimir Kotal
56d93b0c761868f813ac0bc0b5bc21a7a9fefd89Vladimir Kotal if (tv->tv_sec > 0 || (tv->tv_sec == 0 && tv->tv_usec > 0))
4f3c0816485669143aa54f1c6461fcb47cf5bc5cVladimir Kotal return tv->tv_sec*1000 + tv->tv_usec/1000;
4f3c0816485669143aa54f1c6461fcb47cf5bc5cVladimir Kotal
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco /* no need to calculate the times again with this timeout */
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray tv->tv_sec = tv->tv_usec = 0;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray timeout->run_now = TRUE;
17d95a647aba8c37d9ac34d97e4eed729aa46f67Naseer Ahmed return 0;
17d95a647aba8c37d9ac34d97e4eed729aa46f67Naseer Ahmed}
17d95a647aba8c37d9ac34d97e4eed729aa46f67Naseer Ahmed
5762c9f28c2246777be0e9d49cb29d9c0f49146dLubos Koscovoid io_loop_handle_timeouts(struct ioloop *ioloop)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray{
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray struct timeout *t, *next;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray struct timeval tv;
5762c9f28c2246777be0e9d49cb29d9c0f49146dLubos Kosco unsigned int t_id;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d6ee3934a24d8ccc0e4bb478405d8e5f6a35825dLubos Kosco gettimeofday(&ioloop_timeval, &ioloop_timezone);
477c09a2656e6a2c1075425ad81e61d594164fa9Lubos Kosco ioloop_time = ioloop_timeval.tv_sec;
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco
d6ee3934a24d8ccc0e4bb478405d8e5f6a35825dLubos Kosco if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
c842732324ee4c74ede17887ad1f0dcdc4364a2cLubos Kosco return;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
b17cb0705d90907337b3528aa7b8ed1700806f26Vladimir Kotal for (t = ioloop->timeouts; t != NULL; t = next) {
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal next = t->next;
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal
8f8c3f4555e5aa3160f03f2e9c55ddbd3381357bLubos Kosco if (t->destroyed) {
9dc24f2da404ab474e38fc4d428e5717dc9bcee4Vladimir Kotal timeout_destroy(ioloop, t);
8f8c3f4555e5aa3160f03f2e9c55ddbd3381357bLubos Kosco continue;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray }
d70dc22c6dce3f498251b0873638d1fea0e644a3Lubos Kosco
477c09a2656e6a2c1075425ad81e61d594164fa9Lubos Kosco if (!t->run_now) {
d70dc22c6dce3f498251b0873638d1fea0e644a3Lubos Kosco io_loop_get_wait_time(t, &tv, &ioloop_timeval);
d70dc22c6dce3f498251b0873638d1fea0e644a3Lubos Kosco
d70dc22c6dce3f498251b0873638d1fea0e644a3Lubos Kosco if (!t->run_now)
d70dc22c6dce3f498251b0873638d1fea0e644a3Lubos Kosco break;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray }
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco t->run_now = FALSE;
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco timeout_update_next(t, &ioloop_timeval);
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco t_id = t_push();
2cf31ec93bd5d8a2efeab511ce051da51e69aedaLubos Kosco t->func(t->context, t);
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray if (t_pop() != t_id)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray i_panic("Leaked a t_pop() call!");
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray }
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray}
1a5c2ab40bd94d2b2c63afda767ce7bbf29ecc4bJan Friedel
5762c9f28c2246777be0e9d49cb29d9c0f49146dLubos Koscovoid io_loop_run(struct ioloop *ioloop)
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray{
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray ioloop->running = TRUE;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal while (ioloop->running)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal io_loop_handler_run(ioloop);
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal}
5baba343b1d32252619db7e6aff0c1c0be67761cjethrogb
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotalvoid io_loop_stop(struct ioloop *ioloop)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal{
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal ioloop->running = FALSE;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal}
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotalvoid io_loop_set_running(struct ioloop *ioloop)
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal{
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal ioloop->running = TRUE;
6c8465e3b4611cb632cba9b0572e3e3737c8c341Vladimir Kotal}
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smetstruct ioloop *io_loop_create(pool_t pool)
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet{
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet struct ioloop *ioloop;
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet /* initialize time */
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet gettimeofday(&ioloop_timeval, &ioloop_timezone);
6ce0623fa4ef95af9d77700a1c9c19ec1a919326Guillaume Smet ioloop_time = ioloop_timeval.tv_sec;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray
cd71fb134e037849c77364b50940b1870c4684ceVladimir Kotal ioloop = p_new(pool, struct ioloop, 1);
983523cf73bc85cce6282cb5aa78b60f6bcd959fLubos Kosco pool_ref(pool);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray ioloop->pool = pool;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray ioloop->highest_fd = -1;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray io_loop_handler_init(ioloop);
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco ioloop->prev = current_ioloop;
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco current_ioloop = ioloop;
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco return ioloop;
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco}
0ca9a2c194523c517c3aafe5758e217ac88d6baaLubos Kosco
cd348e325366620fe047edcc849e3c9424828599Peter Brayvoid io_loop_destroy(struct ioloop *ioloop)
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray{
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray while (ioloop->ios != NULL) {
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray struct io *io = ioloop->ios;
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray if (!io->destroyed) {
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray i_warning("I/O leak: %p (%d)",
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco (void *) io->func, io->fd);
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco io_remove(io);
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco }
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco io_destroy(ioloop, io);
2b024356b830395446c55f50f9f724a63612e578Lubos Kosco }
d2a02e104622a26dd90fa88f4f17188f2039809fPeter Bray
cd348e325366620fe047edcc849e3c9424828599Peter Bray while (ioloop->timeouts != NULL) {
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray struct timeout *to = ioloop->timeouts;
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray
4e854c69a0484765dcd27b0e837898c8b6969beaTrond Norbye if (!to->destroyed) {
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray i_warning("Timeout leak: %p", (void *) to->func);
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray timeout_remove(to);
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray }
d280c5e286f5b98be13237f52281ae5afdcf51b9Peter Bray timeout_destroy(ioloop, to);
477c09a2656e6a2c1075425ad81e61d594164fa9Lubos Kosco }
477c09a2656e6a2c1075425ad81e61d594164fa9Lubos Kosco
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal io_loop_handler_deinit(ioloop);
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal /* ->prev won't work unless loops are destroyed in create order */
83439b4ed8fe40097dc3f2c05168d26bd7926159Vladimir Kotal i_assert(ioloop == current_ioloop);
477c09a2656e6a2c1075425ad81e61d594164fa9Lubos Kosco current_ioloop = current_ioloop->prev;
cd348e325366620fe047edcc849e3c9424828599Peter Bray
3ba66fbb56ef22f183da783a1b2718280c357a4eStanislav Kozina pool_unref(ioloop->pool);
3ba66fbb56ef22f183da783a1b2718280c357a4eStanislav Kozina}
3ba66fbb56ef22f183da783a1b2718280c357a4eStanislav Kozina