1ee65b806SJan Lentfer /* 2ee65b806SJan Lentfer * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3ee65b806SJan Lentfer * Copyright (c) 1995-1999 by Internet Software Consortium 4ee65b806SJan Lentfer * 5ee65b806SJan Lentfer * Permission to use, copy, modify, and distribute this software for any 6ee65b806SJan Lentfer * purpose with or without fee is hereby granted, provided that the above 7ee65b806SJan Lentfer * copyright notice and this permission notice appear in all copies. 8ee65b806SJan Lentfer * 9ee65b806SJan Lentfer * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10ee65b806SJan Lentfer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11ee65b806SJan Lentfer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12ee65b806SJan Lentfer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13ee65b806SJan Lentfer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14ee65b806SJan Lentfer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15ee65b806SJan Lentfer * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16ee65b806SJan Lentfer */ 17ee65b806SJan Lentfer 18ee65b806SJan Lentfer /* ev_timers.c - implement timers for the eventlib 19ee65b806SJan Lentfer * vix 09sep95 [initial] 20ee65b806SJan Lentfer */ 21ee65b806SJan Lentfer 22ee65b806SJan Lentfer #if !defined(LINT) && !defined(CODECENTER) 23ee65b806SJan Lentfer static const char rcsid[] = "$Id: ev_timers.c,v 1.6 2005/04/27 04:56:36 sra Exp $"; 24ee65b806SJan Lentfer #endif 25ee65b806SJan Lentfer 26ee65b806SJan Lentfer /* Import. */ 27ee65b806SJan Lentfer 28ee65b806SJan Lentfer #include "port_before.h" 29ee65b806SJan Lentfer #ifndef _LIBC 30ee65b806SJan Lentfer #include "fd_setsize.h" 31ee65b806SJan Lentfer #endif 32ee65b806SJan Lentfer 33ee65b806SJan Lentfer #include <errno.h> 34ee65b806SJan Lentfer 35ee65b806SJan Lentfer #ifndef _LIBC 36ee65b806SJan Lentfer #include <isc/assertions.h> 37ee65b806SJan Lentfer #endif 38ee65b806SJan Lentfer #include "isc/eventlib.h" 39ee65b806SJan Lentfer #include "eventlib_p.h" 40ee65b806SJan Lentfer 41ee65b806SJan Lentfer #include "port_after.h" 42ee65b806SJan Lentfer 43ee65b806SJan Lentfer /* Constants. */ 44ee65b806SJan Lentfer 45ee65b806SJan Lentfer #define MILLION 1000000 46ee65b806SJan Lentfer #define BILLION 1000000000 47ee65b806SJan Lentfer 48ee65b806SJan Lentfer /* Forward. */ 49ee65b806SJan Lentfer #ifdef _LIBC 50ee65b806SJan Lentfer static int __evOptMonoTime; 51ee65b806SJan Lentfer #else 52ee65b806SJan Lentfer static int due_sooner(void *, void *); 53ee65b806SJan Lentfer static void set_index(void *, int); 54ee65b806SJan Lentfer static void free_timer(void *, void *); 55ee65b806SJan Lentfer static void print_timer(void *, void *); 56ee65b806SJan Lentfer static void idle_timeout(evContext, void *, struct timespec, struct timespec); 57ee65b806SJan Lentfer 58ee65b806SJan Lentfer /* Private type. */ 59ee65b806SJan Lentfer 60ee65b806SJan Lentfer typedef struct { 61ee65b806SJan Lentfer evTimerFunc func; 62ee65b806SJan Lentfer void * uap; 63ee65b806SJan Lentfer struct timespec lastTouched; 64ee65b806SJan Lentfer struct timespec max_idle; 65ee65b806SJan Lentfer evTimer * timer; 66ee65b806SJan Lentfer } idle_timer; 67ee65b806SJan Lentfer #endif 68ee65b806SJan Lentfer /* Public. */ 69ee65b806SJan Lentfer 70ee65b806SJan Lentfer struct timespec 71ee65b806SJan Lentfer evConsTime(time_t sec, long nsec) { 72ee65b806SJan Lentfer struct timespec x; 73ee65b806SJan Lentfer 74ee65b806SJan Lentfer x.tv_sec = sec; 75ee65b806SJan Lentfer x.tv_nsec = nsec; 76ee65b806SJan Lentfer return (x); 77ee65b806SJan Lentfer } 78ee65b806SJan Lentfer 79ee65b806SJan Lentfer struct timespec 80ee65b806SJan Lentfer evAddTime(struct timespec addend1, struct timespec addend2) { 81ee65b806SJan Lentfer struct timespec x; 82ee65b806SJan Lentfer 83ee65b806SJan Lentfer x.tv_sec = addend1.tv_sec + addend2.tv_sec; 84ee65b806SJan Lentfer x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; 85ee65b806SJan Lentfer if (x.tv_nsec >= BILLION) { 86ee65b806SJan Lentfer x.tv_sec++; 87ee65b806SJan Lentfer x.tv_nsec -= BILLION; 88ee65b806SJan Lentfer } 89ee65b806SJan Lentfer return (x); 90ee65b806SJan Lentfer } 91ee65b806SJan Lentfer 92ee65b806SJan Lentfer struct timespec 93ee65b806SJan Lentfer evSubTime(struct timespec minuend, struct timespec subtrahend) { 94ee65b806SJan Lentfer struct timespec x; 95ee65b806SJan Lentfer 96ee65b806SJan Lentfer x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; 97ee65b806SJan Lentfer if (minuend.tv_nsec >= subtrahend.tv_nsec) 98ee65b806SJan Lentfer x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; 99ee65b806SJan Lentfer else { 100ee65b806SJan Lentfer x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; 101ee65b806SJan Lentfer x.tv_sec--; 102ee65b806SJan Lentfer } 103ee65b806SJan Lentfer return (x); 104ee65b806SJan Lentfer } 105ee65b806SJan Lentfer 106ee65b806SJan Lentfer int 107ee65b806SJan Lentfer evCmpTime(struct timespec a, struct timespec b) { 108ee65b806SJan Lentfer long x = a.tv_sec - b.tv_sec; 109ee65b806SJan Lentfer 110ee65b806SJan Lentfer if (x == 0L) 111ee65b806SJan Lentfer x = a.tv_nsec - b.tv_nsec; 112ee65b806SJan Lentfer return (x < 0L ? (-1) : x > 0L ? (1) : (0)); 113ee65b806SJan Lentfer } 114ee65b806SJan Lentfer 115ee65b806SJan Lentfer struct timespec 116*5d7d35b1SSascha Wildner evNowTime(void) { 117ee65b806SJan Lentfer struct timeval now; 118ee65b806SJan Lentfer #ifdef CLOCK_REALTIME 119ee65b806SJan Lentfer struct timespec tsnow; 120ee65b806SJan Lentfer int m = CLOCK_REALTIME; 121ee65b806SJan Lentfer 122ee65b806SJan Lentfer #ifdef CLOCK_MONOTONIC 123ee65b806SJan Lentfer if (__evOptMonoTime) 124ee65b806SJan Lentfer m = CLOCK_MONOTONIC; 125ee65b806SJan Lentfer #endif 126ee65b806SJan Lentfer if (clock_gettime(m, &tsnow) == 0) 127ee65b806SJan Lentfer return (tsnow); 128ee65b806SJan Lentfer #endif 129ee65b806SJan Lentfer if (gettimeofday(&now, NULL) < 0) 130ee65b806SJan Lentfer return (evConsTime(0, 0)); 131ee65b806SJan Lentfer return (evTimeSpec(now)); 132ee65b806SJan Lentfer } 133ee65b806SJan Lentfer 134ee65b806SJan Lentfer struct timespec 135*5d7d35b1SSascha Wildner evUTCTime(void) { 136ee65b806SJan Lentfer struct timeval now; 137ee65b806SJan Lentfer #ifdef CLOCK_REALTIME 138ee65b806SJan Lentfer struct timespec tsnow; 139ee65b806SJan Lentfer if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0) 140ee65b806SJan Lentfer return (tsnow); 141ee65b806SJan Lentfer #endif 142ee65b806SJan Lentfer if (gettimeofday(&now, NULL) < 0) 143ee65b806SJan Lentfer return (evConsTime(0, 0)); 144ee65b806SJan Lentfer return (evTimeSpec(now)); 145ee65b806SJan Lentfer } 146ee65b806SJan Lentfer 147ee65b806SJan Lentfer #ifndef _LIBC 148ee65b806SJan Lentfer struct timespec 149ee65b806SJan Lentfer evLastEventTime(evContext opaqueCtx) { 150ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 151ee65b806SJan Lentfer 152ee65b806SJan Lentfer return (ctx->lastEventTime); 153ee65b806SJan Lentfer } 154ee65b806SJan Lentfer #endif 155ee65b806SJan Lentfer 156ee65b806SJan Lentfer struct timespec 157ee65b806SJan Lentfer evTimeSpec(struct timeval tv) { 158ee65b806SJan Lentfer struct timespec ts; 159ee65b806SJan Lentfer 160ee65b806SJan Lentfer ts.tv_sec = tv.tv_sec; 161ee65b806SJan Lentfer ts.tv_nsec = tv.tv_usec * 1000; 162ee65b806SJan Lentfer return (ts); 163ee65b806SJan Lentfer } 164ee65b806SJan Lentfer #if !defined(USE_KQUEUE) || !defined(_LIBC) 165ee65b806SJan Lentfer struct timeval 166ee65b806SJan Lentfer evTimeVal(struct timespec ts) { 167ee65b806SJan Lentfer struct timeval tv; 168ee65b806SJan Lentfer 169ee65b806SJan Lentfer tv.tv_sec = ts.tv_sec; 170ee65b806SJan Lentfer tv.tv_usec = ts.tv_nsec / 1000; 171ee65b806SJan Lentfer return (tv); 172ee65b806SJan Lentfer } 173ee65b806SJan Lentfer #endif 174ee65b806SJan Lentfer 175ee65b806SJan Lentfer #ifndef _LIBC 176ee65b806SJan Lentfer int 177ee65b806SJan Lentfer evSetTimer(evContext opaqueCtx, 178ee65b806SJan Lentfer evTimerFunc func, 179ee65b806SJan Lentfer void *uap, 180ee65b806SJan Lentfer struct timespec due, 181ee65b806SJan Lentfer struct timespec inter, 182ee65b806SJan Lentfer evTimerID *opaqueID 183ee65b806SJan Lentfer ) { 184ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 185ee65b806SJan Lentfer evTimer *id; 186ee65b806SJan Lentfer 187ee65b806SJan Lentfer evPrintf(ctx, 1, 188ee65b806SJan Lentfer "evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n", 189ee65b806SJan Lentfer ctx, func, uap, 190ee65b806SJan Lentfer (long)due.tv_sec, due.tv_nsec, 191ee65b806SJan Lentfer (long)inter.tv_sec, inter.tv_nsec); 192ee65b806SJan Lentfer 193ee65b806SJan Lentfer #ifdef __hpux 194ee65b806SJan Lentfer /* 195ee65b806SJan Lentfer * tv_sec and tv_nsec are unsigned. 196ee65b806SJan Lentfer */ 197ee65b806SJan Lentfer if (due.tv_nsec >= BILLION) 198ee65b806SJan Lentfer EV_ERR(EINVAL); 199ee65b806SJan Lentfer 200ee65b806SJan Lentfer if (inter.tv_nsec >= BILLION) 201ee65b806SJan Lentfer EV_ERR(EINVAL); 202ee65b806SJan Lentfer #else 203ee65b806SJan Lentfer if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) 204ee65b806SJan Lentfer EV_ERR(EINVAL); 205ee65b806SJan Lentfer 206ee65b806SJan Lentfer if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) 207ee65b806SJan Lentfer EV_ERR(EINVAL); 208ee65b806SJan Lentfer #endif 209ee65b806SJan Lentfer 210ee65b806SJan Lentfer /* due={0,0} is a magic cookie meaning "now." */ 211ee65b806SJan Lentfer if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L) 212ee65b806SJan Lentfer due = evNowTime(); 213ee65b806SJan Lentfer 214ee65b806SJan Lentfer /* Allocate and fill. */ 215ee65b806SJan Lentfer OKNEW(id); 216ee65b806SJan Lentfer id->func = func; 217ee65b806SJan Lentfer id->uap = uap; 218ee65b806SJan Lentfer id->due = due; 219ee65b806SJan Lentfer id->inter = inter; 220ee65b806SJan Lentfer 221ee65b806SJan Lentfer if (heap_insert(ctx->timers, id) < 0) 222ee65b806SJan Lentfer return (-1); 223ee65b806SJan Lentfer 224ee65b806SJan Lentfer /* Remember the ID if the caller provided us a place for it. */ 225ee65b806SJan Lentfer if (opaqueID) 226ee65b806SJan Lentfer opaqueID->opaque = id; 227ee65b806SJan Lentfer 228ee65b806SJan Lentfer if (ctx->debug > 7) { 229ee65b806SJan Lentfer evPrintf(ctx, 7, "timers after evSetTimer:\n"); 230ee65b806SJan Lentfer (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 231ee65b806SJan Lentfer } 232ee65b806SJan Lentfer 233ee65b806SJan Lentfer return (0); 234ee65b806SJan Lentfer } 235ee65b806SJan Lentfer 236ee65b806SJan Lentfer int 237ee65b806SJan Lentfer evClearTimer(evContext opaqueCtx, evTimerID id) { 238ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 239ee65b806SJan Lentfer evTimer *del = id.opaque; 240ee65b806SJan Lentfer 241ee65b806SJan Lentfer if (ctx->cur != NULL && 242ee65b806SJan Lentfer ctx->cur->type == Timer && 243ee65b806SJan Lentfer ctx->cur->u.timer.this == del) { 244ee65b806SJan Lentfer evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); 245ee65b806SJan Lentfer /* 246ee65b806SJan Lentfer * Setting the interval to zero ensures that evDrop() will 247ee65b806SJan Lentfer * clean up the timer. 248ee65b806SJan Lentfer */ 249ee65b806SJan Lentfer del->inter = evConsTime(0, 0); 250ee65b806SJan Lentfer return (0); 251ee65b806SJan Lentfer } 252ee65b806SJan Lentfer 253ee65b806SJan Lentfer if (heap_element(ctx->timers, del->index) != del) 254ee65b806SJan Lentfer EV_ERR(ENOENT); 255ee65b806SJan Lentfer 256ee65b806SJan Lentfer if (heap_delete(ctx->timers, del->index) < 0) 257ee65b806SJan Lentfer return (-1); 258ee65b806SJan Lentfer FREE(del); 259ee65b806SJan Lentfer 260ee65b806SJan Lentfer if (ctx->debug > 7) { 261ee65b806SJan Lentfer evPrintf(ctx, 7, "timers after evClearTimer:\n"); 262ee65b806SJan Lentfer (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 263ee65b806SJan Lentfer } 264ee65b806SJan Lentfer 265ee65b806SJan Lentfer return (0); 266ee65b806SJan Lentfer } 267ee65b806SJan Lentfer 268ee65b806SJan Lentfer int 269ee65b806SJan Lentfer evConfigTimer(evContext opaqueCtx, 270ee65b806SJan Lentfer evTimerID id, 271ee65b806SJan Lentfer const char *param, 272ee65b806SJan Lentfer int value 273ee65b806SJan Lentfer ) { 274ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 275ee65b806SJan Lentfer evTimer *timer = id.opaque; 276ee65b806SJan Lentfer int result=0; 277ee65b806SJan Lentfer 278ee65b806SJan Lentfer UNUSED(value); 279ee65b806SJan Lentfer 280ee65b806SJan Lentfer if (heap_element(ctx->timers, timer->index) != timer) 281ee65b806SJan Lentfer EV_ERR(ENOENT); 282ee65b806SJan Lentfer 283ee65b806SJan Lentfer if (strcmp(param, "rate") == 0) 284ee65b806SJan Lentfer timer->mode |= EV_TMR_RATE; 285ee65b806SJan Lentfer else if (strcmp(param, "interval") == 0) 286ee65b806SJan Lentfer timer->mode &= ~EV_TMR_RATE; 287ee65b806SJan Lentfer else 288ee65b806SJan Lentfer EV_ERR(EINVAL); 289ee65b806SJan Lentfer 290ee65b806SJan Lentfer return (result); 291ee65b806SJan Lentfer } 292ee65b806SJan Lentfer 293ee65b806SJan Lentfer int 294ee65b806SJan Lentfer evResetTimer(evContext opaqueCtx, 295ee65b806SJan Lentfer evTimerID id, 296ee65b806SJan Lentfer evTimerFunc func, 297ee65b806SJan Lentfer void *uap, 298ee65b806SJan Lentfer struct timespec due, 299ee65b806SJan Lentfer struct timespec inter 300ee65b806SJan Lentfer ) { 301ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 302ee65b806SJan Lentfer evTimer *timer = id.opaque; 303ee65b806SJan Lentfer struct timespec old_due; 304ee65b806SJan Lentfer int result=0; 305ee65b806SJan Lentfer 306ee65b806SJan Lentfer if (heap_element(ctx->timers, timer->index) != timer) 307ee65b806SJan Lentfer EV_ERR(ENOENT); 308ee65b806SJan Lentfer 309ee65b806SJan Lentfer #ifdef __hpux 310ee65b806SJan Lentfer /* 311ee65b806SJan Lentfer * tv_sec and tv_nsec are unsigned. 312ee65b806SJan Lentfer */ 313ee65b806SJan Lentfer if (due.tv_nsec >= BILLION) 314ee65b806SJan Lentfer EV_ERR(EINVAL); 315ee65b806SJan Lentfer 316ee65b806SJan Lentfer if (inter.tv_nsec >= BILLION) 317ee65b806SJan Lentfer EV_ERR(EINVAL); 318ee65b806SJan Lentfer #else 319ee65b806SJan Lentfer if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) 320ee65b806SJan Lentfer EV_ERR(EINVAL); 321ee65b806SJan Lentfer 322ee65b806SJan Lentfer if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) 323ee65b806SJan Lentfer EV_ERR(EINVAL); 324ee65b806SJan Lentfer #endif 325ee65b806SJan Lentfer 326ee65b806SJan Lentfer old_due = timer->due; 327ee65b806SJan Lentfer 328ee65b806SJan Lentfer timer->func = func; 329ee65b806SJan Lentfer timer->uap = uap; 330ee65b806SJan Lentfer timer->due = due; 331ee65b806SJan Lentfer timer->inter = inter; 332ee65b806SJan Lentfer 333ee65b806SJan Lentfer switch (evCmpTime(due, old_due)) { 334ee65b806SJan Lentfer case -1: 335ee65b806SJan Lentfer result = heap_increased(ctx->timers, timer->index); 336ee65b806SJan Lentfer break; 337ee65b806SJan Lentfer case 0: 338ee65b806SJan Lentfer result = 0; 339ee65b806SJan Lentfer break; 340ee65b806SJan Lentfer case 1: 341ee65b806SJan Lentfer result = heap_decreased(ctx->timers, timer->index); 342ee65b806SJan Lentfer break; 343ee65b806SJan Lentfer } 344ee65b806SJan Lentfer 345ee65b806SJan Lentfer if (ctx->debug > 7) { 346ee65b806SJan Lentfer evPrintf(ctx, 7, "timers after evResetTimer:\n"); 347ee65b806SJan Lentfer (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 348ee65b806SJan Lentfer } 349ee65b806SJan Lentfer 350ee65b806SJan Lentfer return (result); 351ee65b806SJan Lentfer } 352ee65b806SJan Lentfer 353ee65b806SJan Lentfer int 354ee65b806SJan Lentfer evSetIdleTimer(evContext opaqueCtx, 355ee65b806SJan Lentfer evTimerFunc func, 356ee65b806SJan Lentfer void *uap, 357ee65b806SJan Lentfer struct timespec max_idle, 358ee65b806SJan Lentfer evTimerID *opaqueID 359ee65b806SJan Lentfer ) { 360ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 361ee65b806SJan Lentfer idle_timer *tt; 362ee65b806SJan Lentfer 363ee65b806SJan Lentfer /* Allocate and fill. */ 364ee65b806SJan Lentfer OKNEW(tt); 365ee65b806SJan Lentfer tt->func = func; 366ee65b806SJan Lentfer tt->uap = uap; 367ee65b806SJan Lentfer tt->lastTouched = ctx->lastEventTime; 368ee65b806SJan Lentfer tt->max_idle = max_idle; 369ee65b806SJan Lentfer 370ee65b806SJan Lentfer if (evSetTimer(opaqueCtx, idle_timeout, tt, 371ee65b806SJan Lentfer evAddTime(ctx->lastEventTime, max_idle), 372ee65b806SJan Lentfer max_idle, opaqueID) < 0) { 373ee65b806SJan Lentfer FREE(tt); 374ee65b806SJan Lentfer return (-1); 375ee65b806SJan Lentfer } 376ee65b806SJan Lentfer 377ee65b806SJan Lentfer tt->timer = opaqueID->opaque; 378ee65b806SJan Lentfer 379ee65b806SJan Lentfer return (0); 380ee65b806SJan Lentfer } 381ee65b806SJan Lentfer 382ee65b806SJan Lentfer int 383ee65b806SJan Lentfer evClearIdleTimer(evContext opaqueCtx, evTimerID id) { 384ee65b806SJan Lentfer evTimer *del = id.opaque; 385ee65b806SJan Lentfer idle_timer *tt = del->uap; 386ee65b806SJan Lentfer 387ee65b806SJan Lentfer FREE(tt); 388ee65b806SJan Lentfer return (evClearTimer(opaqueCtx, id)); 389ee65b806SJan Lentfer } 390ee65b806SJan Lentfer 391ee65b806SJan Lentfer int 392ee65b806SJan Lentfer evResetIdleTimer(evContext opaqueCtx, 393ee65b806SJan Lentfer evTimerID opaqueID, 394ee65b806SJan Lentfer evTimerFunc func, 395ee65b806SJan Lentfer void *uap, 396ee65b806SJan Lentfer struct timespec max_idle 397ee65b806SJan Lentfer ) { 398ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 399ee65b806SJan Lentfer evTimer *timer = opaqueID.opaque; 400ee65b806SJan Lentfer idle_timer *tt = timer->uap; 401ee65b806SJan Lentfer 402ee65b806SJan Lentfer tt->func = func; 403ee65b806SJan Lentfer tt->uap = uap; 404ee65b806SJan Lentfer tt->lastTouched = ctx->lastEventTime; 405ee65b806SJan Lentfer tt->max_idle = max_idle; 406ee65b806SJan Lentfer 407ee65b806SJan Lentfer return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, 408ee65b806SJan Lentfer evAddTime(ctx->lastEventTime, max_idle), 409ee65b806SJan Lentfer max_idle)); 410ee65b806SJan Lentfer } 411ee65b806SJan Lentfer 412ee65b806SJan Lentfer int 413ee65b806SJan Lentfer evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { 414ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 415ee65b806SJan Lentfer evTimer *t = id.opaque; 416ee65b806SJan Lentfer idle_timer *tt = t->uap; 417ee65b806SJan Lentfer 418ee65b806SJan Lentfer tt->lastTouched = ctx->lastEventTime; 419ee65b806SJan Lentfer 420ee65b806SJan Lentfer return (0); 421ee65b806SJan Lentfer } 422ee65b806SJan Lentfer 423ee65b806SJan Lentfer /* Public to the rest of eventlib. */ 424ee65b806SJan Lentfer 425ee65b806SJan Lentfer heap_context 426ee65b806SJan Lentfer evCreateTimers(const evContext_p *ctx) { 427ee65b806SJan Lentfer 428ee65b806SJan Lentfer UNUSED(ctx); 429ee65b806SJan Lentfer 430ee65b806SJan Lentfer return (heap_new(due_sooner, set_index, 2048)); 431ee65b806SJan Lentfer } 432ee65b806SJan Lentfer 433ee65b806SJan Lentfer void 434ee65b806SJan Lentfer evDestroyTimers(const evContext_p *ctx) { 435ee65b806SJan Lentfer (void) heap_for_each(ctx->timers, free_timer, NULL); 436ee65b806SJan Lentfer (void) heap_free(ctx->timers); 437ee65b806SJan Lentfer } 438ee65b806SJan Lentfer 439ee65b806SJan Lentfer /* Private. */ 440ee65b806SJan Lentfer 441ee65b806SJan Lentfer static int 442ee65b806SJan Lentfer due_sooner(void *a, void *b) { 443ee65b806SJan Lentfer evTimer *a_timer, *b_timer; 444ee65b806SJan Lentfer 445ee65b806SJan Lentfer a_timer = a; 446ee65b806SJan Lentfer b_timer = b; 447ee65b806SJan Lentfer return (evCmpTime(a_timer->due, b_timer->due) < 0); 448ee65b806SJan Lentfer } 449ee65b806SJan Lentfer 450ee65b806SJan Lentfer static void 451ee65b806SJan Lentfer set_index(void *what, int index) { 452ee65b806SJan Lentfer evTimer *timer; 453ee65b806SJan Lentfer 454ee65b806SJan Lentfer timer = what; 455ee65b806SJan Lentfer timer->index = index; 456ee65b806SJan Lentfer } 457ee65b806SJan Lentfer 458ee65b806SJan Lentfer static void 459ee65b806SJan Lentfer free_timer(void *what, void *uap) { 460ee65b806SJan Lentfer evTimer *t = what; 461ee65b806SJan Lentfer 462ee65b806SJan Lentfer UNUSED(uap); 463ee65b806SJan Lentfer 464ee65b806SJan Lentfer FREE(t); 465ee65b806SJan Lentfer } 466ee65b806SJan Lentfer 467ee65b806SJan Lentfer static void 468ee65b806SJan Lentfer print_timer(void *what, void *uap) { 469ee65b806SJan Lentfer evTimer *cur = what; 470ee65b806SJan Lentfer evContext_p *ctx = uap; 471ee65b806SJan Lentfer 472ee65b806SJan Lentfer cur = what; 473ee65b806SJan Lentfer evPrintf(ctx, 7, 474ee65b806SJan Lentfer " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n", 475ee65b806SJan Lentfer cur->func, cur->uap, 476ee65b806SJan Lentfer (long)cur->due.tv_sec, cur->due.tv_nsec, 477ee65b806SJan Lentfer (long)cur->inter.tv_sec, cur->inter.tv_nsec); 478ee65b806SJan Lentfer } 479ee65b806SJan Lentfer 480ee65b806SJan Lentfer static void 481ee65b806SJan Lentfer idle_timeout(evContext opaqueCtx, 482ee65b806SJan Lentfer void *uap, 483ee65b806SJan Lentfer struct timespec due, 484ee65b806SJan Lentfer struct timespec inter 485ee65b806SJan Lentfer ) { 486ee65b806SJan Lentfer evContext_p *ctx = opaqueCtx.opaque; 487ee65b806SJan Lentfer idle_timer *this = uap; 488ee65b806SJan Lentfer struct timespec idle; 489ee65b806SJan Lentfer 490ee65b806SJan Lentfer UNUSED(due); 491ee65b806SJan Lentfer UNUSED(inter); 492ee65b806SJan Lentfer 493ee65b806SJan Lentfer idle = evSubTime(ctx->lastEventTime, this->lastTouched); 494ee65b806SJan Lentfer if (evCmpTime(idle, this->max_idle) >= 0) { 495ee65b806SJan Lentfer (this->func)(opaqueCtx, this->uap, this->timer->due, 496ee65b806SJan Lentfer this->max_idle); 497ee65b806SJan Lentfer /* 498ee65b806SJan Lentfer * Setting the interval to zero will cause the timer to 499ee65b806SJan Lentfer * be cleaned up in evDrop(). 500ee65b806SJan Lentfer */ 501ee65b806SJan Lentfer this->timer->inter = evConsTime(0, 0); 502ee65b806SJan Lentfer FREE(this); 503ee65b806SJan Lentfer } else { 504ee65b806SJan Lentfer /* evDrop() will reschedule the timer. */ 505ee65b806SJan Lentfer this->timer->inter = evSubTime(this->max_idle, idle); 506ee65b806SJan Lentfer } 507ee65b806SJan Lentfer } 508ee65b806SJan Lentfer #endif /* !_LIBC */ 509ee65b806SJan Lentfer 510ee65b806SJan Lentfer /*! \file */ 511