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