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 $
43 static struct rtadvd_timer timer_head
;
45 #define MILLION 1000000
46 #define TIMEVAL_EQUAL(t1,t2) ((t1)->tv_sec == (t2)->tv_sec &&\
47 (t1)->tv_usec == (t2)->tv_usec)
49 static struct timeval tm_max
= {0x7fffffff, 0x7fffffff};
52 rtadvd_timer_init(void)
54 memset(&timer_head
, 0, sizeof(timer_head
));
56 timer_head
.next
= timer_head
.prev
= &timer_head
;
57 timer_head
.tm
= tm_max
;
61 rtadvd_add_timer(struct rtadvd_timer
*(*timeout
)(void *),
62 void (*update
)(void *, struct timeval
*),
63 void *timeodata
, void *updatedata
)
65 struct rtadvd_timer
*newtimer
;
67 if ((newtimer
= malloc(sizeof(*newtimer
))) == NULL
) {
69 "<%s> can't allocate memory", __func__
);
73 memset(newtimer
, 0, sizeof(*newtimer
));
75 if (timeout
== NULL
) {
77 "<%s> timeout function unspecfied", __func__
);
80 newtimer
->expire
= timeout
;
81 newtimer
->update
= update
;
82 newtimer
->expire_data
= timeodata
;
83 newtimer
->update_data
= updatedata
;
84 newtimer
->tm
= tm_max
;
87 insque(newtimer
, &timer_head
);
93 rtadvd_remove_timer(struct rtadvd_timer
**timer
)
101 rtadvd_set_timer(struct timeval
*tm
, struct rtadvd_timer
*timer
)
105 /* reset the timer */
106 gettimeofday(&now
, NULL
);
108 TIMEVAL_ADD(&now
, tm
, &timer
->tm
);
110 /* update the next expiration time */
111 if (TIMEVAL_LT(timer
->tm
, timer_head
.tm
))
112 timer_head
.tm
= timer
->tm
;
118 * Check expiration for each timer. If a timer expires,
119 * call the expire function for the timer and update the timer.
120 * Return the next interval for select() call.
123 rtadvd_check_timer(void)
125 static struct timeval returnval
;
127 struct rtadvd_timer
*tm
= timer_head
.next
, *tm_next
;
129 gettimeofday(&now
, NULL
);
131 timer_head
.tm
= tm_max
;
133 for (tm
= timer_head
.next
; tm
!= &timer_head
; tm
= tm_next
) {
136 if (TIMEVAL_LEQ(tm
->tm
, now
)) {
137 if (((*tm
->expire
)(tm
->expire_data
) == NULL
))
138 continue; /* the timer was removed */
140 (*tm
->update
)(tm
->update_data
, &tm
->tm
);
141 TIMEVAL_ADD(&tm
->tm
, &now
, &tm
->tm
);
144 if (TIMEVAL_LT(tm
->tm
, timer_head
.tm
))
145 timer_head
.tm
= tm
->tm
;
148 if (TIMEVAL_EQUAL(&tm_max
, &timer_head
.tm
)) {
149 /* no need to timeout */
152 else if (TIMEVAL_LT(timer_head
.tm
, now
)) {
153 /* this may occur when the interval is too small */
154 returnval
.tv_sec
= returnval
.tv_usec
= 0;
157 TIMEVAL_SUB(&timer_head
.tm
, &now
, &returnval
);
162 rtadvd_timer_rest(struct rtadvd_timer
*timer
)
164 static struct timeval returnval
, now
;
166 gettimeofday(&now
, NULL
);
167 if (TIMEVAL_LEQ(timer
->tm
, now
)) {
169 "<%s> a timer must be expired, but not yet",
171 returnval
.tv_sec
= returnval
.tv_usec
= 0;
174 TIMEVAL_SUB(&timer
->tm
, &now
, &returnval
);
181 TIMEVAL_ADD(struct timeval
*a
, struct timeval
*b
, struct timeval
*result
)
185 if ((l
= a
->tv_usec
+ b
->tv_usec
) < MILLION
) {
187 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
;
190 result
->tv_usec
= l
- MILLION
;
191 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
+ 1;
197 * XXX: this function assumes that a >= b.
200 TIMEVAL_SUB(struct timeval
*a
, struct timeval
*b
, struct timeval
*result
)
204 if ((l
= a
->tv_usec
- b
->tv_usec
) >= 0) {
206 result
->tv_sec
= a
->tv_sec
- b
->tv_sec
;
209 result
->tv_usec
= MILLION
+ l
;
210 result
->tv_sec
= a
->tv_sec
- b
->tv_sec
- 1;