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