xref: /titanic_52/usr/src/lib/libresolv2/common/isc/ev_timers.c (revision 9525b14bcdeb5b5f6f95ab27c2f48f18bd2ec829)
17c478bd9Sstevel@tonic-gate /*
2*9525b14bSRao Shoaib  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
37c478bd9Sstevel@tonic-gate  * Copyright (c) 1995-1999 by Internet Software Consortium
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software for any
67c478bd9Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
77c478bd9Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
87c478bd9Sstevel@tonic-gate  *
9*9525b14bSRao Shoaib  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*9525b14bSRao Shoaib  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*9525b14bSRao Shoaib  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12*9525b14bSRao Shoaib  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*9525b14bSRao Shoaib  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*9525b14bSRao Shoaib  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*9525b14bSRao Shoaib  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate /* ev_timers.c - implement timers for the eventlib
197c478bd9Sstevel@tonic-gate  * vix 09sep95 [initial]
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
23*9525b14bSRao Shoaib static const char rcsid[] = "$Id: ev_timers.c,v 1.6 2005/04/27 04:56:36 sra Exp $";
247c478bd9Sstevel@tonic-gate #endif
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /* Import. */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include "port_before.h"
297c478bd9Sstevel@tonic-gate #include "fd_setsize.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
347c478bd9Sstevel@tonic-gate #include <isc/eventlib.h>
357c478bd9Sstevel@tonic-gate #include "eventlib_p.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "port_after.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* Constants. */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #define	MILLION 1000000
427c478bd9Sstevel@tonic-gate #define BILLION 1000000000
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /* Forward. */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate static int due_sooner(void *, void *);
477c478bd9Sstevel@tonic-gate static void set_index(void *, int);
487c478bd9Sstevel@tonic-gate static void free_timer(void *, void *);
497c478bd9Sstevel@tonic-gate static void print_timer(void *, void *);
507c478bd9Sstevel@tonic-gate static void idle_timeout(evContext, void *, struct timespec, struct timespec);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /* Private type. */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate typedef struct {
557c478bd9Sstevel@tonic-gate 	evTimerFunc	func;
567c478bd9Sstevel@tonic-gate 	void *		uap;
577c478bd9Sstevel@tonic-gate 	struct timespec	lastTouched;
587c478bd9Sstevel@tonic-gate 	struct timespec	max_idle;
597c478bd9Sstevel@tonic-gate 	evTimer *	timer;
607c478bd9Sstevel@tonic-gate } idle_timer;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /* Public. */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate struct timespec
657c478bd9Sstevel@tonic-gate evConsTime(time_t sec, long nsec) {
667c478bd9Sstevel@tonic-gate 	struct timespec x;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	x.tv_sec = sec;
697c478bd9Sstevel@tonic-gate 	x.tv_nsec = nsec;
707c478bd9Sstevel@tonic-gate 	return (x);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate struct timespec
747c478bd9Sstevel@tonic-gate evAddTime(struct timespec addend1, struct timespec addend2) {
757c478bd9Sstevel@tonic-gate 	struct timespec x;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	x.tv_sec = addend1.tv_sec + addend2.tv_sec;
787c478bd9Sstevel@tonic-gate 	x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
797c478bd9Sstevel@tonic-gate 	if (x.tv_nsec >= BILLION) {
807c478bd9Sstevel@tonic-gate 		x.tv_sec++;
817c478bd9Sstevel@tonic-gate 		x.tv_nsec -= BILLION;
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 	return (x);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate struct timespec
877c478bd9Sstevel@tonic-gate evSubTime(struct timespec minuend, struct timespec subtrahend) {
887c478bd9Sstevel@tonic-gate 	struct timespec x;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
917c478bd9Sstevel@tonic-gate 	if (minuend.tv_nsec >= subtrahend.tv_nsec)
927c478bd9Sstevel@tonic-gate 		x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
937c478bd9Sstevel@tonic-gate 	else {
947c478bd9Sstevel@tonic-gate 		x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
957c478bd9Sstevel@tonic-gate 		x.tv_sec--;
967c478bd9Sstevel@tonic-gate 	}
977c478bd9Sstevel@tonic-gate 	return (x);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate int
1017c478bd9Sstevel@tonic-gate evCmpTime(struct timespec a, struct timespec b) {
1027c478bd9Sstevel@tonic-gate 	long x = a.tv_sec - b.tv_sec;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (x == 0L)
1057c478bd9Sstevel@tonic-gate 		x = a.tv_nsec - b.tv_nsec;
1067c478bd9Sstevel@tonic-gate 	return (x < 0L ? (-1) : x > 0L ? (1) : (0));
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate struct timespec
1107c478bd9Sstevel@tonic-gate evNowTime() {
1117c478bd9Sstevel@tonic-gate 	struct timeval now;
112*9525b14bSRao Shoaib #ifdef CLOCK_REALTIME
113*9525b14bSRao Shoaib 	struct timespec tsnow;
114*9525b14bSRao Shoaib 	int m = CLOCK_REALTIME;
1157c478bd9Sstevel@tonic-gate 
116*9525b14bSRao Shoaib #ifdef CLOCK_MONOTONIC
117*9525b14bSRao Shoaib 	if (__evOptMonoTime)
118*9525b14bSRao Shoaib 		m = CLOCK_MONOTONIC;
119*9525b14bSRao Shoaib #endif
120*9525b14bSRao Shoaib 	if (clock_gettime(m, &tsnow) == 0)
121*9525b14bSRao Shoaib 		return (tsnow);
122*9525b14bSRao Shoaib #endif
123*9525b14bSRao Shoaib 	if (gettimeofday(&now, NULL) < 0)
124*9525b14bSRao Shoaib 		return (evConsTime(0, 0));
125*9525b14bSRao Shoaib 	return (evTimeSpec(now));
126*9525b14bSRao Shoaib }
127*9525b14bSRao Shoaib 
128*9525b14bSRao Shoaib struct timespec
129*9525b14bSRao Shoaib evUTCTime() {
130*9525b14bSRao Shoaib 	struct timeval now;
131*9525b14bSRao Shoaib #ifdef CLOCK_REALTIME
132*9525b14bSRao Shoaib 	struct timespec tsnow;
133*9525b14bSRao Shoaib 	if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0)
134*9525b14bSRao Shoaib 		return (tsnow);
135*9525b14bSRao Shoaib #endif
1367c478bd9Sstevel@tonic-gate 	if (gettimeofday(&now, NULL) < 0)
1377c478bd9Sstevel@tonic-gate 		return (evConsTime(0, 0));
1387c478bd9Sstevel@tonic-gate 	return (evTimeSpec(now));
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate struct timespec
1427c478bd9Sstevel@tonic-gate evLastEventTime(evContext opaqueCtx) {
1437c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	return (ctx->lastEventTime);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate struct timespec
1497c478bd9Sstevel@tonic-gate evTimeSpec(struct timeval tv) {
1507c478bd9Sstevel@tonic-gate 	struct timespec ts;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	ts.tv_sec = tv.tv_sec;
1537c478bd9Sstevel@tonic-gate 	ts.tv_nsec = tv.tv_usec * 1000;
1547c478bd9Sstevel@tonic-gate 	return (ts);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate struct timeval
1587c478bd9Sstevel@tonic-gate evTimeVal(struct timespec ts) {
1597c478bd9Sstevel@tonic-gate 	struct timeval tv;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	tv.tv_sec = ts.tv_sec;
1627c478bd9Sstevel@tonic-gate 	tv.tv_usec = ts.tv_nsec / 1000;
1637c478bd9Sstevel@tonic-gate 	return (tv);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate int
1677c478bd9Sstevel@tonic-gate evSetTimer(evContext opaqueCtx,
1687c478bd9Sstevel@tonic-gate 	   evTimerFunc func,
1697c478bd9Sstevel@tonic-gate 	   void *uap,
1707c478bd9Sstevel@tonic-gate 	   struct timespec due,
1717c478bd9Sstevel@tonic-gate 	   struct timespec inter,
1727c478bd9Sstevel@tonic-gate 	   evTimerID *opaqueID
1737c478bd9Sstevel@tonic-gate ) {
1747c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1757c478bd9Sstevel@tonic-gate 	evTimer *id;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	evPrintf(ctx, 1,
1787c478bd9Sstevel@tonic-gate "evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
1797c478bd9Sstevel@tonic-gate 		 ctx, func, uap,
1807c478bd9Sstevel@tonic-gate 		 (long)due.tv_sec, due.tv_nsec,
1817c478bd9Sstevel@tonic-gate 		 (long)inter.tv_sec, inter.tv_nsec);
1827c478bd9Sstevel@tonic-gate 
183*9525b14bSRao Shoaib #ifdef __hpux
184*9525b14bSRao Shoaib 	/*
185*9525b14bSRao Shoaib 	 * tv_sec and tv_nsec are unsigned.
186*9525b14bSRao Shoaib 	 */
187*9525b14bSRao Shoaib 	if (due.tv_nsec >= BILLION)
188*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
189*9525b14bSRao Shoaib 
190*9525b14bSRao Shoaib 	if (inter.tv_nsec >= BILLION)
191*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
192*9525b14bSRao Shoaib #else
193*9525b14bSRao Shoaib 	if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
194*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
195*9525b14bSRao Shoaib 
196*9525b14bSRao Shoaib 	if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
197*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
198*9525b14bSRao Shoaib #endif
199*9525b14bSRao Shoaib 
2007c478bd9Sstevel@tonic-gate 	/* due={0,0} is a magic cookie meaning "now." */
201*9525b14bSRao Shoaib 	if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L)
2027c478bd9Sstevel@tonic-gate 		due = evNowTime();
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	/* Allocate and fill. */
2057c478bd9Sstevel@tonic-gate 	OKNEW(id);
2067c478bd9Sstevel@tonic-gate 	id->func = func;
2077c478bd9Sstevel@tonic-gate 	id->uap = uap;
2087c478bd9Sstevel@tonic-gate 	id->due = due;
2097c478bd9Sstevel@tonic-gate 	id->inter = inter;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (heap_insert(ctx->timers, id) < 0)
2127c478bd9Sstevel@tonic-gate 		return (-1);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/* Remember the ID if the caller provided us a place for it. */
2157c478bd9Sstevel@tonic-gate 	if (opaqueID)
2167c478bd9Sstevel@tonic-gate 		opaqueID->opaque = id;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	if (ctx->debug > 7) {
2197c478bd9Sstevel@tonic-gate 		evPrintf(ctx, 7, "timers after evSetTimer:\n");
2207c478bd9Sstevel@tonic-gate 		(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	return (0);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate int
2277c478bd9Sstevel@tonic-gate evClearTimer(evContext opaqueCtx, evTimerID id) {
2287c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
2297c478bd9Sstevel@tonic-gate 	evTimer *del = id.opaque;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (ctx->cur != NULL &&
2327c478bd9Sstevel@tonic-gate 	    ctx->cur->type == Timer &&
2337c478bd9Sstevel@tonic-gate 	    ctx->cur->u.timer.this == del) {
2347c478bd9Sstevel@tonic-gate 		evPrintf(ctx, 8, "deferring delete of timer (executing)\n");
2357c478bd9Sstevel@tonic-gate 		/*
2367c478bd9Sstevel@tonic-gate 		 * Setting the interval to zero ensures that evDrop() will
2377c478bd9Sstevel@tonic-gate 		 * clean up the timer.
2387c478bd9Sstevel@tonic-gate 		 */
2397c478bd9Sstevel@tonic-gate 		del->inter = evConsTime(0, 0);
2407c478bd9Sstevel@tonic-gate 		return (0);
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	if (heap_element(ctx->timers, del->index) != del)
2447c478bd9Sstevel@tonic-gate 		EV_ERR(ENOENT);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if (heap_delete(ctx->timers, del->index) < 0)
2477c478bd9Sstevel@tonic-gate 		return (-1);
2487c478bd9Sstevel@tonic-gate 	FREE(del);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	if (ctx->debug > 7) {
2517c478bd9Sstevel@tonic-gate 		evPrintf(ctx, 7, "timers after evClearTimer:\n");
2527c478bd9Sstevel@tonic-gate 		(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	return (0);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate int
259*9525b14bSRao Shoaib evConfigTimer(evContext opaqueCtx,
260*9525b14bSRao Shoaib 	     evTimerID id,
261*9525b14bSRao Shoaib 	     const char *param,
262*9525b14bSRao Shoaib 	     int value
263*9525b14bSRao Shoaib ) {
264*9525b14bSRao Shoaib 	evContext_p *ctx = opaqueCtx.opaque;
265*9525b14bSRao Shoaib 	evTimer *timer = id.opaque;
266*9525b14bSRao Shoaib 	int result=0;
267*9525b14bSRao Shoaib 
268*9525b14bSRao Shoaib 	UNUSED(value);
269*9525b14bSRao Shoaib 
270*9525b14bSRao Shoaib 	if (heap_element(ctx->timers, timer->index) != timer)
271*9525b14bSRao Shoaib 		EV_ERR(ENOENT);
272*9525b14bSRao Shoaib 
273*9525b14bSRao Shoaib 	if (strcmp(param, "rate") == 0)
274*9525b14bSRao Shoaib 		timer->mode |= EV_TMR_RATE;
275*9525b14bSRao Shoaib 	else if (strcmp(param, "interval") == 0)
276*9525b14bSRao Shoaib 		timer->mode &= ~EV_TMR_RATE;
277*9525b14bSRao Shoaib 	else
278*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
279*9525b14bSRao Shoaib 
280*9525b14bSRao Shoaib 	return (result);
281*9525b14bSRao Shoaib }
282*9525b14bSRao Shoaib 
283*9525b14bSRao Shoaib int
2847c478bd9Sstevel@tonic-gate evResetTimer(evContext opaqueCtx,
2857c478bd9Sstevel@tonic-gate 	     evTimerID id,
2867c478bd9Sstevel@tonic-gate 	     evTimerFunc func,
2877c478bd9Sstevel@tonic-gate 	     void *uap,
2887c478bd9Sstevel@tonic-gate 	     struct timespec due,
2897c478bd9Sstevel@tonic-gate 	     struct timespec inter
2907c478bd9Sstevel@tonic-gate ) {
2917c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
2927c478bd9Sstevel@tonic-gate 	evTimer *timer = id.opaque;
2937c478bd9Sstevel@tonic-gate 	struct timespec old_due;
2947c478bd9Sstevel@tonic-gate 	int result=0;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	if (heap_element(ctx->timers, timer->index) != timer)
2977c478bd9Sstevel@tonic-gate 		EV_ERR(ENOENT);
2987c478bd9Sstevel@tonic-gate 
299*9525b14bSRao Shoaib #ifdef __hpux
300*9525b14bSRao Shoaib 	/*
301*9525b14bSRao Shoaib 	 * tv_sec and tv_nsec are unsigned.
302*9525b14bSRao Shoaib 	 */
303*9525b14bSRao Shoaib 	if (due.tv_nsec >= BILLION)
304*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
305*9525b14bSRao Shoaib 
306*9525b14bSRao Shoaib 	if (inter.tv_nsec >= BILLION)
307*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
308*9525b14bSRao Shoaib #else
309*9525b14bSRao Shoaib 	if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
310*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
311*9525b14bSRao Shoaib 
312*9525b14bSRao Shoaib 	if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
313*9525b14bSRao Shoaib 		EV_ERR(EINVAL);
314*9525b14bSRao Shoaib #endif
315*9525b14bSRao Shoaib 
3167c478bd9Sstevel@tonic-gate 	old_due = timer->due;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	timer->func = func;
3197c478bd9Sstevel@tonic-gate 	timer->uap = uap;
3207c478bd9Sstevel@tonic-gate 	timer->due = due;
3217c478bd9Sstevel@tonic-gate 	timer->inter = inter;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	switch (evCmpTime(due, old_due)) {
3247c478bd9Sstevel@tonic-gate 	case -1:
3257c478bd9Sstevel@tonic-gate 		result = heap_increased(ctx->timers, timer->index);
3267c478bd9Sstevel@tonic-gate 		break;
3277c478bd9Sstevel@tonic-gate 	case 0:
3287c478bd9Sstevel@tonic-gate 		result = 0;
3297c478bd9Sstevel@tonic-gate 		break;
3307c478bd9Sstevel@tonic-gate 	case 1:
3317c478bd9Sstevel@tonic-gate 		result = heap_decreased(ctx->timers, timer->index);
3327c478bd9Sstevel@tonic-gate 		break;
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	if (ctx->debug > 7) {
3367c478bd9Sstevel@tonic-gate 		evPrintf(ctx, 7, "timers after evResetTimer:\n");
3377c478bd9Sstevel@tonic-gate 		(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	return (result);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate int
3447c478bd9Sstevel@tonic-gate evSetIdleTimer(evContext opaqueCtx,
3457c478bd9Sstevel@tonic-gate 		evTimerFunc func,
3467c478bd9Sstevel@tonic-gate 		void *uap,
3477c478bd9Sstevel@tonic-gate 		struct timespec max_idle,
3487c478bd9Sstevel@tonic-gate 		evTimerID *opaqueID
3497c478bd9Sstevel@tonic-gate ) {
3507c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
3517c478bd9Sstevel@tonic-gate 	idle_timer *tt;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/* Allocate and fill. */
3547c478bd9Sstevel@tonic-gate 	OKNEW(tt);
3557c478bd9Sstevel@tonic-gate 	tt->func = func;
3567c478bd9Sstevel@tonic-gate 	tt->uap = uap;
3577c478bd9Sstevel@tonic-gate 	tt->lastTouched = ctx->lastEventTime;
3587c478bd9Sstevel@tonic-gate 	tt->max_idle = max_idle;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (evSetTimer(opaqueCtx, idle_timeout, tt,
3617c478bd9Sstevel@tonic-gate 		       evAddTime(ctx->lastEventTime, max_idle),
3627c478bd9Sstevel@tonic-gate 		       max_idle, opaqueID) < 0) {
3637c478bd9Sstevel@tonic-gate 		FREE(tt);
3647c478bd9Sstevel@tonic-gate 		return (-1);
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	tt->timer = opaqueID->opaque;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	return (0);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate int
3737c478bd9Sstevel@tonic-gate evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
3747c478bd9Sstevel@tonic-gate 	evTimer *del = id.opaque;
3757c478bd9Sstevel@tonic-gate 	idle_timer *tt = del->uap;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	FREE(tt);
3787c478bd9Sstevel@tonic-gate 	return (evClearTimer(opaqueCtx, id));
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate int
3827c478bd9Sstevel@tonic-gate evResetIdleTimer(evContext opaqueCtx,
3837c478bd9Sstevel@tonic-gate 		 evTimerID opaqueID,
3847c478bd9Sstevel@tonic-gate 		 evTimerFunc func,
3857c478bd9Sstevel@tonic-gate 		 void *uap,
3867c478bd9Sstevel@tonic-gate 		 struct timespec max_idle
3877c478bd9Sstevel@tonic-gate ) {
3887c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
3897c478bd9Sstevel@tonic-gate 	evTimer *timer = opaqueID.opaque;
3907c478bd9Sstevel@tonic-gate 	idle_timer *tt = timer->uap;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	tt->func = func;
3937c478bd9Sstevel@tonic-gate 	tt->uap = uap;
3947c478bd9Sstevel@tonic-gate 	tt->lastTouched = ctx->lastEventTime;
3957c478bd9Sstevel@tonic-gate 	tt->max_idle = max_idle;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt,
3987c478bd9Sstevel@tonic-gate 			     evAddTime(ctx->lastEventTime, max_idle),
3997c478bd9Sstevel@tonic-gate 			     max_idle));
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate int
4037c478bd9Sstevel@tonic-gate evTouchIdleTimer(evContext opaqueCtx, evTimerID id) {
4047c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
4057c478bd9Sstevel@tonic-gate 	evTimer *t = id.opaque;
4067c478bd9Sstevel@tonic-gate 	idle_timer *tt = t->uap;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	tt->lastTouched = ctx->lastEventTime;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	return (0);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate /* Public to the rest of eventlib. */
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate heap_context
4167c478bd9Sstevel@tonic-gate evCreateTimers(const evContext_p *ctx) {
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	UNUSED(ctx);
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	return (heap_new(due_sooner, set_index, 2048));
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate void
4247c478bd9Sstevel@tonic-gate evDestroyTimers(const evContext_p *ctx) {
4257c478bd9Sstevel@tonic-gate 	(void) heap_for_each(ctx->timers, free_timer, NULL);
4267c478bd9Sstevel@tonic-gate 	(void) heap_free(ctx->timers);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /* Private. */
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate static int
4327c478bd9Sstevel@tonic-gate due_sooner(void *a, void *b) {
4337c478bd9Sstevel@tonic-gate 	evTimer *a_timer, *b_timer;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	a_timer = a;
4367c478bd9Sstevel@tonic-gate 	b_timer = b;
4377c478bd9Sstevel@tonic-gate 	return (evCmpTime(a_timer->due, b_timer->due) < 0);
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate static void
4417c478bd9Sstevel@tonic-gate set_index(void *what, int index) {
4427c478bd9Sstevel@tonic-gate 	evTimer *timer;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	timer = what;
4457c478bd9Sstevel@tonic-gate 	timer->index = index;
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate static void
4497c478bd9Sstevel@tonic-gate free_timer(void *what, void *uap) {
4507c478bd9Sstevel@tonic-gate 	evTimer *t = what;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	UNUSED(uap);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	FREE(t);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate static void
4587c478bd9Sstevel@tonic-gate print_timer(void *what, void *uap) {
4597c478bd9Sstevel@tonic-gate 	evTimer *cur = what;
4607c478bd9Sstevel@tonic-gate 	evContext_p *ctx = uap;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	cur = what;
4637c478bd9Sstevel@tonic-gate 	evPrintf(ctx, 7,
4647c478bd9Sstevel@tonic-gate 	    "  func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n",
4657c478bd9Sstevel@tonic-gate 		 cur->func, cur->uap,
4667c478bd9Sstevel@tonic-gate 		 (long)cur->due.tv_sec, cur->due.tv_nsec,
4677c478bd9Sstevel@tonic-gate 		 (long)cur->inter.tv_sec, cur->inter.tv_nsec);
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate static void
4717c478bd9Sstevel@tonic-gate idle_timeout(evContext opaqueCtx,
4727c478bd9Sstevel@tonic-gate 	     void *uap,
4737c478bd9Sstevel@tonic-gate 	     struct timespec due,
4747c478bd9Sstevel@tonic-gate 	     struct timespec inter
4757c478bd9Sstevel@tonic-gate ) {
4767c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
4777c478bd9Sstevel@tonic-gate 	idle_timer *this = uap;
4787c478bd9Sstevel@tonic-gate 	struct timespec idle;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	UNUSED(due);
4817c478bd9Sstevel@tonic-gate 	UNUSED(inter);
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	idle = evSubTime(ctx->lastEventTime, this->lastTouched);
4847c478bd9Sstevel@tonic-gate 	if (evCmpTime(idle, this->max_idle) >= 0) {
4857c478bd9Sstevel@tonic-gate 		(this->func)(opaqueCtx, this->uap, this->timer->due,
4867c478bd9Sstevel@tonic-gate 			     this->max_idle);
4877c478bd9Sstevel@tonic-gate 		/*
4887c478bd9Sstevel@tonic-gate 		 * Setting the interval to zero will cause the timer to
4897c478bd9Sstevel@tonic-gate 		 * be cleaned up in evDrop().
4907c478bd9Sstevel@tonic-gate 		 */
4917c478bd9Sstevel@tonic-gate 		this->timer->inter = evConsTime(0, 0);
4927c478bd9Sstevel@tonic-gate 		FREE(this);
4937c478bd9Sstevel@tonic-gate 	} else {
4947c478bd9Sstevel@tonic-gate 		/* evDrop() will reschedule the timer. */
4957c478bd9Sstevel@tonic-gate 		this->timer->inter = evSubTime(this->max_idle, idle);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate }
498*9525b14bSRao Shoaib 
499*9525b14bSRao Shoaib /*! \file */
500