1*0f246c0aSchristos /* $NetBSD: ev_timers.c,v 1.11 2012/03/21 00:34:54 christos Exp $ */
2330989eeSchristos
3330989eeSchristos /*
4330989eeSchristos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5330989eeSchristos * Copyright (c) 1995-1999 by Internet Software Consortium
6330989eeSchristos *
7330989eeSchristos * Permission to use, copy, modify, and distribute this software for any
8330989eeSchristos * purpose with or without fee is hereby granted, provided that the above
9330989eeSchristos * copyright notice and this permission notice appear in all copies.
10330989eeSchristos *
11330989eeSchristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12330989eeSchristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13330989eeSchristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14330989eeSchristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15330989eeSchristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16330989eeSchristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17330989eeSchristos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18330989eeSchristos */
19330989eeSchristos
20330989eeSchristos /* ev_timers.c - implement timers for the eventlib
21330989eeSchristos * vix 09sep95 [initial]
22330989eeSchristos */
23330989eeSchristos
2449a363f1Schristos #include <sys/cdefs.h>
2549a363f1Schristos #if !defined(LINT) && !defined(CODECENTER) && !defined(lint)
2649a363f1Schristos #ifdef notdef
273873655bSchristos static const char rcsid[] = "Id: ev_timers.c,v 1.6 2005/04/27 04:56:36 sra Exp";
2849a363f1Schristos #else
29*0f246c0aSchristos __RCSID("$NetBSD: ev_timers.c,v 1.11 2012/03/21 00:34:54 christos Exp $");
3049a363f1Schristos #endif
31330989eeSchristos #endif
32330989eeSchristos
33330989eeSchristos /* Import. */
34330989eeSchristos
35330989eeSchristos #include "port_before.h"
36330989eeSchristos #include "fd_setsize.h"
37330989eeSchristos
38330989eeSchristos #include <errno.h>
39330989eeSchristos
40330989eeSchristos #include <isc/assertions.h>
41330989eeSchristos #include <isc/eventlib.h>
42330989eeSchristos #include "eventlib_p.h"
43330989eeSchristos
44330989eeSchristos #include "port_after.h"
45330989eeSchristos
46330989eeSchristos /* Constants. */
47330989eeSchristos
48330989eeSchristos #define MILLION 1000000
49330989eeSchristos #define BILLION 1000000000
50330989eeSchristos
51330989eeSchristos /* Forward. */
52330989eeSchristos
5349a363f1Schristos #ifndef _LIBC
54330989eeSchristos static int due_sooner(void *, void *);
55330989eeSchristos static void set_index(void *, int);
56330989eeSchristos static void free_timer(void *, void *);
57330989eeSchristos static void print_timer(void *, void *);
58330989eeSchristos static void idle_timeout(evContext, void *, struct timespec, struct timespec);
59330989eeSchristos
60330989eeSchristos /* Private type. */
61330989eeSchristos
62330989eeSchristos typedef struct {
63330989eeSchristos evTimerFunc func;
64330989eeSchristos void * uap;
65330989eeSchristos struct timespec lastTouched;
66330989eeSchristos struct timespec max_idle;
67330989eeSchristos evTimer * timer;
68330989eeSchristos } idle_timer;
6949a363f1Schristos #endif
70330989eeSchristos
71330989eeSchristos /* Public. */
72330989eeSchristos
73330989eeSchristos struct timespec
evConsTime(time_t sec,long nsec)74330989eeSchristos evConsTime(time_t sec, long nsec) {
75330989eeSchristos struct timespec x;
76330989eeSchristos
77330989eeSchristos x.tv_sec = sec;
78330989eeSchristos x.tv_nsec = nsec;
79330989eeSchristos return (x);
80330989eeSchristos }
81330989eeSchristos
82330989eeSchristos struct timespec
evAddTime(struct timespec addend1,struct timespec addend2)83330989eeSchristos evAddTime(struct timespec addend1, struct timespec addend2) {
84330989eeSchristos struct timespec x;
85330989eeSchristos
86330989eeSchristos x.tv_sec = addend1.tv_sec + addend2.tv_sec;
87330989eeSchristos x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
88330989eeSchristos if (x.tv_nsec >= BILLION) {
89330989eeSchristos x.tv_sec++;
90330989eeSchristos x.tv_nsec -= BILLION;
91330989eeSchristos }
92330989eeSchristos return (x);
93330989eeSchristos }
94330989eeSchristos
95330989eeSchristos struct timespec
evSubTime(struct timespec minuend,struct timespec subtrahend)96330989eeSchristos evSubTime(struct timespec minuend, struct timespec subtrahend) {
97330989eeSchristos struct timespec x;
98330989eeSchristos
99330989eeSchristos x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
100330989eeSchristos if (minuend.tv_nsec >= subtrahend.tv_nsec)
101330989eeSchristos x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
102330989eeSchristos else {
103330989eeSchristos x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
104330989eeSchristos x.tv_sec--;
105330989eeSchristos }
106330989eeSchristos return (x);
107330989eeSchristos }
108330989eeSchristos
109330989eeSchristos int
evCmpTime(struct timespec a,struct timespec b)110330989eeSchristos evCmpTime(struct timespec a, struct timespec b) {
111461a86f9Schristos #define SGN(x) ((x) < 0 ? (-1) : (x) > 0 ? (1) : (0));
112461a86f9Schristos time_t s = a.tv_sec - b.tv_sec;
113461a86f9Schristos long n;
114330989eeSchristos
115461a86f9Schristos if (s != 0)
116461a86f9Schristos return SGN(s);
117461a86f9Schristos
118461a86f9Schristos n = a.tv_nsec - b.tv_nsec;
119461a86f9Schristos return SGN(n);
120330989eeSchristos }
121330989eeSchristos
122330989eeSchristos struct timespec
evNowTime(void)12394a48f81Smatt evNowTime(void)
12494a48f81Smatt {
125330989eeSchristos struct timeval now;
126330989eeSchristos #ifdef CLOCK_REALTIME
127330989eeSchristos struct timespec tsnow;
128330989eeSchristos int m = CLOCK_REALTIME;
129330989eeSchristos
130330989eeSchristos #ifdef CLOCK_MONOTONIC
1316fbd14f0Schristos #ifndef _LIBC
132330989eeSchristos if (__evOptMonoTime)
133330989eeSchristos m = CLOCK_MONOTONIC;
134330989eeSchristos #endif
1356fbd14f0Schristos #endif
136330989eeSchristos if (clock_gettime(m, &tsnow) == 0)
137330989eeSchristos return (tsnow);
138330989eeSchristos #endif
139330989eeSchristos if (gettimeofday(&now, NULL) < 0)
140*0f246c0aSchristos return (evConsTime((time_t)0, 0L));
141330989eeSchristos return (evTimeSpec(now));
142330989eeSchristos }
143330989eeSchristos
144330989eeSchristos struct timespec
evUTCTime(void)14549a363f1Schristos evUTCTime(void) {
146330989eeSchristos struct timeval now;
147330989eeSchristos #ifdef CLOCK_REALTIME
148330989eeSchristos struct timespec tsnow;
149330989eeSchristos if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0)
150330989eeSchristos return (tsnow);
151330989eeSchristos #endif
152330989eeSchristos if (gettimeofday(&now, NULL) < 0)
153*0f246c0aSchristos return (evConsTime((time_t)0, 0L));
154330989eeSchristos return (evTimeSpec(now));
155330989eeSchristos }
156330989eeSchristos
15749a363f1Schristos #ifndef _LIBC
158330989eeSchristos struct timespec
evLastEventTime(evContext opaqueCtx)159330989eeSchristos evLastEventTime(evContext opaqueCtx) {
160330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
161330989eeSchristos
162330989eeSchristos return (ctx->lastEventTime);
163330989eeSchristos }
16449a363f1Schristos #endif
165330989eeSchristos
166330989eeSchristos struct timespec
evTimeSpec(struct timeval tv)167330989eeSchristos evTimeSpec(struct timeval tv) {
168330989eeSchristos struct timespec ts;
169330989eeSchristos
170330989eeSchristos ts.tv_sec = tv.tv_sec;
171330989eeSchristos ts.tv_nsec = tv.tv_usec * 1000;
172330989eeSchristos return (ts);
173330989eeSchristos }
174330989eeSchristos
175330989eeSchristos struct timeval
evTimeVal(struct timespec ts)176330989eeSchristos evTimeVal(struct timespec ts) {
177330989eeSchristos struct timeval tv;
178330989eeSchristos
179330989eeSchristos tv.tv_sec = ts.tv_sec;
180e826745eSchristos tv.tv_usec = (suseconds_t)(ts.tv_nsec / 1000);
181330989eeSchristos return (tv);
182330989eeSchristos }
183330989eeSchristos
18449a363f1Schristos #ifndef _LIBC
185330989eeSchristos int
evSetTimer(evContext opaqueCtx,evTimerFunc func,void * uap,struct timespec due,struct timespec inter,evTimerID * opaqueID)186330989eeSchristos evSetTimer(evContext opaqueCtx,
187330989eeSchristos evTimerFunc func,
188330989eeSchristos void *uap,
189330989eeSchristos struct timespec due,
190330989eeSchristos struct timespec inter,
191330989eeSchristos evTimerID *opaqueID
192330989eeSchristos ) {
193330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
194330989eeSchristos evTimer *id;
195330989eeSchristos
196330989eeSchristos evPrintf(ctx, 1,
197330989eeSchristos "evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
198330989eeSchristos ctx, func, uap,
199330989eeSchristos (long)due.tv_sec, due.tv_nsec,
200330989eeSchristos (long)inter.tv_sec, inter.tv_nsec);
201330989eeSchristos
202330989eeSchristos #ifdef __hpux
203330989eeSchristos /*
204330989eeSchristos * tv_sec and tv_nsec are unsigned.
205330989eeSchristos */
206330989eeSchristos if (due.tv_nsec >= BILLION)
207330989eeSchristos EV_ERR(EINVAL);
208330989eeSchristos
209330989eeSchristos if (inter.tv_nsec >= BILLION)
210330989eeSchristos EV_ERR(EINVAL);
211330989eeSchristos #else
212330989eeSchristos if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
213330989eeSchristos EV_ERR(EINVAL);
214330989eeSchristos
215330989eeSchristos if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
216330989eeSchristos EV_ERR(EINVAL);
217330989eeSchristos #endif
218330989eeSchristos
219330989eeSchristos /* due={0,0} is a magic cookie meaning "now." */
220330989eeSchristos if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L)
221330989eeSchristos due = evNowTime();
222330989eeSchristos
223330989eeSchristos /* Allocate and fill. */
224330989eeSchristos OKNEW(id);
225330989eeSchristos id->func = func;
226330989eeSchristos id->uap = uap;
227330989eeSchristos id->due = due;
228330989eeSchristos id->inter = inter;
229330989eeSchristos
230330989eeSchristos if (heap_insert(ctx->timers, id) < 0)
231330989eeSchristos return (-1);
232330989eeSchristos
233330989eeSchristos /* Remember the ID if the caller provided us a place for it. */
234330989eeSchristos if (opaqueID)
235330989eeSchristos opaqueID->opaque = id;
236330989eeSchristos
237330989eeSchristos if (ctx->debug > 7) {
238330989eeSchristos evPrintf(ctx, 7, "timers after evSetTimer:\n");
239330989eeSchristos (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
240330989eeSchristos }
241330989eeSchristos
242330989eeSchristos return (0);
243330989eeSchristos }
244330989eeSchristos
245330989eeSchristos int
evClearTimer(evContext opaqueCtx,evTimerID id)246330989eeSchristos evClearTimer(evContext opaqueCtx, evTimerID id) {
247330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
248330989eeSchristos evTimer *del = id.opaque;
249330989eeSchristos
250330989eeSchristos if (ctx->cur != NULL &&
251330989eeSchristos ctx->cur->type == Timer &&
252330989eeSchristos ctx->cur->u.timer.this == del) {
253330989eeSchristos evPrintf(ctx, 8, "deferring delete of timer (executing)\n");
254330989eeSchristos /*
255330989eeSchristos * Setting the interval to zero ensures that evDrop() will
256330989eeSchristos * clean up the timer.
257330989eeSchristos */
258330989eeSchristos del->inter = evConsTime(0, 0);
259330989eeSchristos return (0);
260330989eeSchristos }
261330989eeSchristos
262330989eeSchristos if (heap_element(ctx->timers, del->index) != del)
263330989eeSchristos EV_ERR(ENOENT);
264330989eeSchristos
265330989eeSchristos if (heap_delete(ctx->timers, del->index) < 0)
266330989eeSchristos return (-1);
267330989eeSchristos FREE(del);
268330989eeSchristos
269330989eeSchristos if (ctx->debug > 7) {
270330989eeSchristos evPrintf(ctx, 7, "timers after evClearTimer:\n");
271330989eeSchristos (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
272330989eeSchristos }
273330989eeSchristos
274330989eeSchristos return (0);
275330989eeSchristos }
276330989eeSchristos
277330989eeSchristos int
evConfigTimer(evContext opaqueCtx,evTimerID id,const char * param,int value)278330989eeSchristos evConfigTimer(evContext opaqueCtx,
279330989eeSchristos evTimerID id,
280330989eeSchristos const char *param,
281330989eeSchristos int value
282330989eeSchristos ) {
283330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
284330989eeSchristos evTimer *timer = id.opaque;
285330989eeSchristos int result=0;
286330989eeSchristos
287330989eeSchristos UNUSED(value);
288330989eeSchristos
289330989eeSchristos if (heap_element(ctx->timers, timer->index) != timer)
290330989eeSchristos EV_ERR(ENOENT);
291330989eeSchristos
292330989eeSchristos if (strcmp(param, "rate") == 0)
293330989eeSchristos timer->mode |= EV_TMR_RATE;
294330989eeSchristos else if (strcmp(param, "interval") == 0)
295330989eeSchristos timer->mode &= ~EV_TMR_RATE;
296330989eeSchristos else
297330989eeSchristos EV_ERR(EINVAL);
298330989eeSchristos
299330989eeSchristos return (result);
300330989eeSchristos }
301330989eeSchristos
302330989eeSchristos int
evResetTimer(evContext opaqueCtx,evTimerID id,evTimerFunc func,void * uap,struct timespec due,struct timespec inter)303330989eeSchristos evResetTimer(evContext opaqueCtx,
304330989eeSchristos evTimerID id,
305330989eeSchristos evTimerFunc func,
306330989eeSchristos void *uap,
307330989eeSchristos struct timespec due,
308330989eeSchristos struct timespec inter
309330989eeSchristos ) {
310330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
311330989eeSchristos evTimer *timer = id.opaque;
312330989eeSchristos struct timespec old_due;
313330989eeSchristos int result=0;
314330989eeSchristos
315330989eeSchristos if (heap_element(ctx->timers, timer->index) != timer)
316330989eeSchristos EV_ERR(ENOENT);
317330989eeSchristos
318330989eeSchristos #ifdef __hpux
319330989eeSchristos /*
320330989eeSchristos * tv_sec and tv_nsec are unsigned.
321330989eeSchristos */
322330989eeSchristos if (due.tv_nsec >= BILLION)
323330989eeSchristos EV_ERR(EINVAL);
324330989eeSchristos
325330989eeSchristos if (inter.tv_nsec >= BILLION)
326330989eeSchristos EV_ERR(EINVAL);
327330989eeSchristos #else
328330989eeSchristos if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
329330989eeSchristos EV_ERR(EINVAL);
330330989eeSchristos
331330989eeSchristos if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
332330989eeSchristos EV_ERR(EINVAL);
333330989eeSchristos #endif
334330989eeSchristos
335330989eeSchristos old_due = timer->due;
336330989eeSchristos
337330989eeSchristos timer->func = func;
338330989eeSchristos timer->uap = uap;
339330989eeSchristos timer->due = due;
340330989eeSchristos timer->inter = inter;
341330989eeSchristos
342330989eeSchristos switch (evCmpTime(due, old_due)) {
343330989eeSchristos case -1:
344330989eeSchristos result = heap_increased(ctx->timers, timer->index);
345330989eeSchristos break;
346330989eeSchristos case 0:
347330989eeSchristos result = 0;
348330989eeSchristos break;
349330989eeSchristos case 1:
350330989eeSchristos result = heap_decreased(ctx->timers, timer->index);
351330989eeSchristos break;
352330989eeSchristos }
353330989eeSchristos
354330989eeSchristos if (ctx->debug > 7) {
355330989eeSchristos evPrintf(ctx, 7, "timers after evResetTimer:\n");
356330989eeSchristos (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
357330989eeSchristos }
358330989eeSchristos
359330989eeSchristos return (result);
360330989eeSchristos }
361330989eeSchristos
362330989eeSchristos int
evSetIdleTimer(evContext opaqueCtx,evTimerFunc func,void * uap,struct timespec max_idle,evTimerID * opaqueID)363330989eeSchristos evSetIdleTimer(evContext opaqueCtx,
364330989eeSchristos evTimerFunc func,
365330989eeSchristos void *uap,
366330989eeSchristos struct timespec max_idle,
367330989eeSchristos evTimerID *opaqueID
368330989eeSchristos ) {
369330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
370330989eeSchristos idle_timer *tt;
371330989eeSchristos
372330989eeSchristos /* Allocate and fill. */
373330989eeSchristos OKNEW(tt);
374330989eeSchristos tt->func = func;
375330989eeSchristos tt->uap = uap;
376330989eeSchristos tt->lastTouched = ctx->lastEventTime;
377330989eeSchristos tt->max_idle = max_idle;
378330989eeSchristos
379330989eeSchristos if (evSetTimer(opaqueCtx, idle_timeout, tt,
380330989eeSchristos evAddTime(ctx->lastEventTime, max_idle),
381330989eeSchristos max_idle, opaqueID) < 0) {
382330989eeSchristos FREE(tt);
383330989eeSchristos return (-1);
384330989eeSchristos }
385330989eeSchristos
386330989eeSchristos tt->timer = opaqueID->opaque;
387330989eeSchristos
388330989eeSchristos return (0);
389330989eeSchristos }
390330989eeSchristos
391330989eeSchristos int
evClearIdleTimer(evContext opaqueCtx,evTimerID id)392330989eeSchristos evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
393330989eeSchristos evTimer *del = id.opaque;
394330989eeSchristos idle_timer *tt = del->uap;
395330989eeSchristos
396330989eeSchristos FREE(tt);
397330989eeSchristos return (evClearTimer(opaqueCtx, id));
398330989eeSchristos }
399330989eeSchristos
400330989eeSchristos int
evResetIdleTimer(evContext opaqueCtx,evTimerID opaqueID,evTimerFunc func,void * uap,struct timespec max_idle)401330989eeSchristos evResetIdleTimer(evContext opaqueCtx,
402330989eeSchristos evTimerID opaqueID,
403330989eeSchristos evTimerFunc func,
404330989eeSchristos void *uap,
405330989eeSchristos struct timespec max_idle
406330989eeSchristos ) {
407330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
408330989eeSchristos evTimer *timer = opaqueID.opaque;
409330989eeSchristos idle_timer *tt = timer->uap;
410330989eeSchristos
411330989eeSchristos tt->func = func;
412330989eeSchristos tt->uap = uap;
413330989eeSchristos tt->lastTouched = ctx->lastEventTime;
414330989eeSchristos tt->max_idle = max_idle;
415330989eeSchristos
416330989eeSchristos return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt,
417330989eeSchristos evAddTime(ctx->lastEventTime, max_idle),
418330989eeSchristos max_idle));
419330989eeSchristos }
420330989eeSchristos
421330989eeSchristos int
evTouchIdleTimer(evContext opaqueCtx,evTimerID id)422330989eeSchristos evTouchIdleTimer(evContext opaqueCtx, evTimerID id) {
423330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
424330989eeSchristos evTimer *t = id.opaque;
425330989eeSchristos idle_timer *tt = t->uap;
426330989eeSchristos
427330989eeSchristos tt->lastTouched = ctx->lastEventTime;
428330989eeSchristos
429330989eeSchristos return (0);
430330989eeSchristos }
431330989eeSchristos
432330989eeSchristos /* Public to the rest of eventlib. */
433330989eeSchristos
434330989eeSchristos heap_context
evCreateTimers(const evContext_p * ctx)435330989eeSchristos evCreateTimers(const evContext_p *ctx) {
436330989eeSchristos
437330989eeSchristos UNUSED(ctx);
438330989eeSchristos
439330989eeSchristos return (heap_new(due_sooner, set_index, 2048));
440330989eeSchristos }
441330989eeSchristos
442330989eeSchristos void
evDestroyTimers(const evContext_p * ctx)443330989eeSchristos evDestroyTimers(const evContext_p *ctx) {
444330989eeSchristos (void) heap_for_each(ctx->timers, free_timer, NULL);
445330989eeSchristos (void) heap_free(ctx->timers);
446330989eeSchristos }
447330989eeSchristos
448330989eeSchristos /* Private. */
449330989eeSchristos
450330989eeSchristos static int
due_sooner(void * a,void * b)451330989eeSchristos due_sooner(void *a, void *b) {
452330989eeSchristos evTimer *a_timer, *b_timer;
453330989eeSchristos
454330989eeSchristos a_timer = a;
455330989eeSchristos b_timer = b;
456330989eeSchristos return (evCmpTime(a_timer->due, b_timer->due) < 0);
457330989eeSchristos }
458330989eeSchristos
459330989eeSchristos static void
set_index(void * what,int idx)46049a363f1Schristos set_index(void *what, int idx) {
461330989eeSchristos evTimer *timer;
462330989eeSchristos
463330989eeSchristos timer = what;
46449a363f1Schristos timer->index = idx;
465330989eeSchristos }
466330989eeSchristos
467330989eeSchristos static void
free_timer(void * what,void * uap)468330989eeSchristos free_timer(void *what, void *uap) {
469330989eeSchristos evTimer *t = what;
470330989eeSchristos
471330989eeSchristos UNUSED(uap);
472330989eeSchristos
473330989eeSchristos FREE(t);
474330989eeSchristos }
475330989eeSchristos
476330989eeSchristos static void
print_timer(void * what,void * uap)477330989eeSchristos print_timer(void *what, void *uap) {
478330989eeSchristos evTimer *cur = what;
479330989eeSchristos evContext_p *ctx = uap;
480330989eeSchristos
481330989eeSchristos cur = what;
482330989eeSchristos evPrintf(ctx, 7,
483330989eeSchristos " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n",
484330989eeSchristos cur->func, cur->uap,
485330989eeSchristos (long)cur->due.tv_sec, cur->due.tv_nsec,
486330989eeSchristos (long)cur->inter.tv_sec, cur->inter.tv_nsec);
487330989eeSchristos }
488330989eeSchristos
489330989eeSchristos static void
idle_timeout(evContext opaqueCtx,void * uap,struct timespec due,struct timespec inter)490330989eeSchristos idle_timeout(evContext opaqueCtx,
491330989eeSchristos void *uap,
492330989eeSchristos struct timespec due,
493330989eeSchristos struct timespec inter
494330989eeSchristos ) {
495330989eeSchristos evContext_p *ctx = opaqueCtx.opaque;
496330989eeSchristos idle_timer *this = uap;
497330989eeSchristos struct timespec idle;
498330989eeSchristos
499330989eeSchristos UNUSED(due);
500330989eeSchristos UNUSED(inter);
501330989eeSchristos
502330989eeSchristos idle = evSubTime(ctx->lastEventTime, this->lastTouched);
503330989eeSchristos if (evCmpTime(idle, this->max_idle) >= 0) {
504330989eeSchristos (this->func)(opaqueCtx, this->uap, this->timer->due,
505330989eeSchristos this->max_idle);
506330989eeSchristos /*
507330989eeSchristos * Setting the interval to zero will cause the timer to
508330989eeSchristos * be cleaned up in evDrop().
509330989eeSchristos */
51049a363f1Schristos this->timer->inter = evConsTime(0L, 0L);
511330989eeSchristos FREE(this);
512330989eeSchristos } else {
513330989eeSchristos /* evDrop() will reschedule the timer. */
514330989eeSchristos this->timer->inter = evSubTime(this->max_idle, idle);
515330989eeSchristos }
516330989eeSchristos }
51749a363f1Schristos #endif
518d73eb73dSchristos
519d73eb73dSchristos /*! \file */
520