diff --git a/src/common.h b/src/common.h index 92d1e89..8e613f9 100644 --- a/src/common.h +++ b/src/common.h @@ -323,9 +323,11 @@ typedef struct { list_head_t links; void (*cb)( void *aux ); void *aux; - time_t timeout; + int64_t timeout; } wakeup_t; +void init_timers( void ); +int64_t get_now( void ); void init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux ); void conf_wakeup( wakeup_t *tmr, int timeout ); void wipe_wakeup( wakeup_t *tmr ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 7074e43..e1024e8 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -3713,7 +3713,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep ) return 0; } - server->sconf.timeout = 20; + server->sconf.timeout = 20000; #ifdef HAVE_LIBSSL server->ssl_type = -1; server->sconf.ssl_versions = -1; @@ -3761,7 +3761,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep ) server->sconf.port = (ushort)port; } } else if (!strcasecmp( "Timeout", cfg->cmd )) { - server->sconf.timeout = parse_int( cfg ); + server->sconf.timeout = parse_int( cfg ) * 1000; } else if (!strcasecmp( "PipelineDepth", cfg->cmd )) { if ((server->max_in_progress = parse_int( cfg )) < 1) { error( "%s:%d: PipelineDepth must be at least 1\n", cfg->file, cfg->line ); diff --git a/src/drv_maildir.c b/src/drv_maildir.c index b904913..60f85f9 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -665,7 +665,7 @@ maildir_store_uidval( maildir_store_t *ctx ) return DRV_BOX_BAD; } } - conf_wakeup( &ctx->lcktmr, 2 ); + conf_wakeup( &ctx->lcktmr, 2000 ); return DRV_OK; } @@ -761,7 +761,7 @@ maildir_uidval_lock( maildir_store_t *ctx ) } } ctx->uvok = 1; - conf_wakeup( &ctx->lcktmr, 2 ); + conf_wakeup( &ctx->lcktmr, 2000 ); return DRV_OK; } diff --git a/src/main.c b/src/main.c index ba467ac..0efd7b8 100644 --- a/src/main.c +++ b/src/main.c @@ -150,6 +150,7 @@ main( int argc, char **argv ) int oind, cops = 0, op, ms_warn = 0, renew_warn = 0, delete_warn = 0; tzset(); + init_timers(); gethostname( Hostname, sizeof(Hostname) ); if ((ochar = strchr( Hostname, '.' ))) *ochar = 0; diff --git a/src/tst_timers.c b/src/tst_timers.c index 5156314..4e1d1ca 100644 --- a/src/tst_timers.c +++ b/src/tst_timers.c @@ -9,7 +9,7 @@ typedef struct { int id; int first, other, morph_at, morph_to; - time_t start; + int64_t start; wakeup_t timer; wakeup_t morph_timer; } tst_t; @@ -18,7 +18,7 @@ static void timer_start( tst_t *timer, int to ) { printf( "starting timer %d, should expire after %d\n", timer->id, to ); - time( &timer->start ); + timer->start = get_now(); conf_wakeup( &timer->timer, to ); } @@ -28,7 +28,7 @@ timed_out( void *aux ) tst_t *timer = (tst_t *)aux; printf( "timer %d expired after %d, repeat %d\n", - timer->id, (int)(time( 0 ) - timer->start), timer->other ); + timer->id, (int)(get_now() - timer->start), timer->other ); if (timer->other >= 0) { timer_start( timer, timer->other ); } else { @@ -44,7 +44,7 @@ morph_timed_out( void *aux ) tst_t *timer = (tst_t *)aux; printf( "morphing timer %d after %d\n", - timer->id, (int)(time( 0 ) - timer->start) ); + timer->id, (int)(get_now() - timer->start) ); timer_start( timer, timer->morph_to ); } @@ -55,6 +55,7 @@ main( int argc, char **argv ) { int i; + init_timers(); for (i = 1; i < argc; i++) { char *val = argv[i]; tst_t *timer = nfmalloc( sizeof(*timer) ); diff --git a/src/util.c b/src/util.c index 767694d..3ba7f91 100644 --- a/src/util.c +++ b/src/util.c @@ -12,6 +12,7 @@ #include #include #include +#include int Verbosity = TERSE; int DFlags; @@ -1000,10 +1001,41 @@ wipe_notifier( notifier_t *sn ) #endif } -static time_t +#if _POSIX_TIMERS - 0 > 0 +static clockid_t clkid; +#endif + +void +init_timers( void ) +{ +#if _POSIX_TIMERS - 0 > 0 + struct timespec ts; +# ifdef CLOCK_BOOTTIME + if (!clock_gettime( CLOCK_BOOTTIME, &ts )) { + clkid = CLOCK_BOOTTIME; + } else +# endif +# ifdef CLOCK_MONOTONIC_COARSE + if (!clock_gettime( CLOCK_MONOTONIC_COARSE, &ts )) { + clkid = CLOCK_MONOTONIC_COARSE; + } else +# endif + clkid = CLOCK_MONOTONIC; +#endif +} + +int64_t get_now( void ) { - return time( NULL ); +#if _POSIX_TIMERS - 0 > 0 + struct timespec ts; + clock_gettime( clkid, &ts ); + return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000; +#else + struct timeval tv; + gettimeofday( &tv, NULL ); + return tv.tv_sec * 1000LL + tv.tv_usec / 1000; +#endif } static list_head_t timers = { &timers, &timers }; @@ -1032,7 +1064,7 @@ conf_wakeup( wakeup_t *tmr, int to ) if (tmr->links.next) list_unlink( &tmr->links ); } else { - time_t timeout = to; + int64_t timeout = to; if (!to) { /* We always prepend null timers, to cluster related events. */ succ = timers.next; @@ -1066,13 +1098,13 @@ event_wait( void ) int timeout = -1; if ((head = timers.next) != &timers) { wakeup_t *tmr = (wakeup_t *)head; - time_t delta = tmr->timeout; + int64_t delta = tmr->timeout; if (!delta || (delta -= get_now()) <= 0) { list_unlink( head ); tmr->cb( tmr->aux ); return; } - timeout = (int)delta * 1000; + timeout = (int)delta; } switch (poll( pollfds, npolls, timeout )) { case 0: @@ -1102,14 +1134,14 @@ event_wait( void ) if ((head = timers.next) != &timers) { wakeup_t *tmr = (wakeup_t *)head; - time_t delta = tmr->timeout; + int64_t delta = tmr->timeout; if (!delta || (delta -= get_now()) <= 0) { list_unlink( head ); tmr->cb( tmr->aux ); return; } - to_tv.tv_sec = delta; - to_tv.tv_usec = 0; + to_tv.tv_sec = delta / 1000; + to_tv.tv_usec = delta * 1000; timeout = &to_tv; } FD_ZERO( &rfds );