1 /* $KAME: timer.c,v 1.4 2000/05/27 11:30:43 jinmei Exp $ */
4 * Copyright (C) 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $FreeBSD: src/usr.sbin/rtadvd/timer.c,v 1.1.2.3 2002/06/29 18:59:53 ume Exp $
32 * $DragonFly: src/usr.sbin/rtadvd/timer.c,v 1.5 2005/12/05 00:56:37 swildner Exp $
41 #if defined(__NetBSD__) || defined(__OpenBSD__)
46 static struct rtadvd_timer timer_head
;
48 #define MILLION 1000000
49 #define TIMEVAL_EQUAL(t1,t2) ((t1)->tv_sec == (t2)->tv_sec &&\
50 (t1)->tv_usec == (t2)->tv_usec)
52 static struct timeval tm_max
= {0x7fffffff, 0x7fffffff};
55 rtadvd_timer_init(void)
57 memset(&timer_head
, 0, sizeof(timer_head
));
59 timer_head
.next
= timer_head
.prev
= &timer_head
;
60 timer_head
.tm
= tm_max
;
64 rtadvd_add_timer(struct rtadvd_timer
*(*timeout
)(void *),
65 void (*update
)(void *, struct timeval
*),
66 void *timeodata
, void *updatedata
)
68 struct rtadvd_timer
*newtimer
;
70 if ((newtimer
= malloc(sizeof(*newtimer
))) == NULL
) {
72 "<%s> can't allocate memory", __func__
);
76 memset(newtimer
, 0, sizeof(*newtimer
));
78 if (timeout
== NULL
) {
80 "<%s> timeout function unspecfied", __func__
);
83 newtimer
->expire
= timeout
;
84 newtimer
->update
= update
;
85 newtimer
->expire_data
= timeodata
;
86 newtimer
->update_data
= updatedata
;
87 newtimer
->tm
= tm_max
;
90 insque(newtimer
, &timer_head
);
96 rtadvd_remove_timer(struct rtadvd_timer
**timer
)
104 rtadvd_set_timer(struct timeval
*tm
, struct rtadvd_timer
*timer
)
108 /* reset the timer */
109 gettimeofday(&now
, NULL
);
111 TIMEVAL_ADD(&now
, tm
, &timer
->tm
);
113 /* update the next expiration time */
114 if (TIMEVAL_LT(timer
->tm
, timer_head
.tm
))
115 timer_head
.tm
= timer
->tm
;
121 * Check expiration for each timer. If a timer expires,
122 * call the expire function for the timer and update the timer.
123 * Return the next interval for select() call.
126 rtadvd_check_timer(void)
128 static struct timeval returnval
;
130 struct rtadvd_timer
*tm
= timer_head
.next
, *tm_next
;
132 gettimeofday(&now
, NULL
);
134 timer_head
.tm
= tm_max
;
136 for (tm
= timer_head
.next
; tm
!= &timer_head
; tm
= tm_next
) {
139 if (TIMEVAL_LEQ(tm
->tm
, now
)) {
140 if (((*tm
->expire
)(tm
->expire_data
) == NULL
))
141 continue; /* the timer was removed */
143 (*tm
->update
)(tm
->update_data
, &tm
->tm
);
144 TIMEVAL_ADD(&tm
->tm
, &now
, &tm
->tm
);
147 if (TIMEVAL_LT(tm
->tm
, timer_head
.tm
))
148 timer_head
.tm
= tm
->tm
;
151 if (TIMEVAL_EQUAL(&tm_max
, &timer_head
.tm
)) {
152 /* no need to timeout */
155 else if (TIMEVAL_LT(timer_head
.tm
, now
)) {
156 /* this may occur when the interval is too small */
157 returnval
.tv_sec
= returnval
.tv_usec
= 0;
160 TIMEVAL_SUB(&timer_head
.tm
, &now
, &returnval
);
165 rtadvd_timer_rest(struct rtadvd_timer
*timer
)
167 static struct timeval returnval
, now
;
169 gettimeofday(&now
, NULL
);
170 if (TIMEVAL_LEQ(timer
->tm
, now
)) {
172 "<%s> a timer must be expired, but not yet",
174 returnval
.tv_sec
= returnval
.tv_usec
= 0;
177 TIMEVAL_SUB(&timer
->tm
, &now
, &returnval
);
184 TIMEVAL_ADD(struct timeval
*a
, struct timeval
*b
, struct timeval
*result
)
188 if ((l
= a
->tv_usec
+ b
->tv_usec
) < MILLION
) {
190 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
;
193 result
->tv_usec
= l
- MILLION
;
194 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
+ 1;
200 * XXX: this function assumes that a >= b.
203 TIMEVAL_SUB(struct timeval
*a
, struct timeval
*b
, struct timeval
*result
)
207 if ((l
= a
->tv_usec
- b
->tv_usec
) >= 0) {
209 result
->tv_sec
= a
->tv_sec
- b
->tv_sec
;
212 result
->tv_usec
= MILLION
+ l
;
213 result
->tv_sec
= a
->tv_sec
- b
->tv_sec
- 1;