1 /* $KAME: timer.c,v 1.6 2003/07/31 23:25:59 jinmei Exp $ */
4 * Copyright (C) 2002 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 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/queue.h>
36 #include <netinet/in.h>
42 #if defined(__NetBSD__) || defined(__OpenBSD__)
50 #define MILLION 1000000
52 LIST_HEAD(, dhcp6_timer
) timer_head
;
53 static struct timeval tm_sentinel
;
54 static struct timeval tm_max
= {0x7fffffff, 0x7fffffff};
56 static void timeval_add
__P((struct timeval
*, struct timeval
*,
62 LIST_INIT(&timer_head
);
67 dhcp6_add_timer(timeout
, timeodata
)
68 struct dhcp6_timer
*(*timeout
) __P((void *));
71 struct dhcp6_timer
*newtimer
;
73 if ((newtimer
= malloc(sizeof(*newtimer
))) == NULL
) {
74 dprintf(LOG_ERR
, FNAME
, "can't allocate memory");
78 memset(newtimer
, 0, sizeof(*newtimer
));
80 if (timeout
== NULL
) {
81 dprintf(LOG_ERR
, FNAME
, "timeout function unspecified");
84 newtimer
->expire
= timeout
;
85 newtimer
->expire_data
= timeodata
;
86 newtimer
->tm
= tm_max
;
88 LIST_INSERT_HEAD(&timer_head
, newtimer
, link
);
94 dhcp6_remove_timer(timer
)
95 struct dhcp6_timer
**timer
;
97 LIST_REMOVE(*timer
, link
);
103 dhcp6_set_timer(tm
, timer
)
105 struct dhcp6_timer
*timer
;
109 /* reset the timer */
110 gettimeofday(&now
, NULL
);
112 timeval_add(&now
, tm
, &timer
->tm
);
114 /* update the next expiration time */
115 if (TIMEVAL_LT(timer
->tm
, tm_sentinel
))
116 tm_sentinel
= timer
->tm
;
122 * Check expiration for each timer. If a timer is expired,
123 * call the expire function for the timer and update the timer.
124 * Return the next interval for select() call.
129 static struct timeval returnval
;
131 struct dhcp6_timer
*tm
, *tm_next
;
133 gettimeofday(&now
, NULL
);
135 tm_sentinel
= tm_max
;
136 for (tm
= LIST_FIRST(&timer_head
); tm
; tm
= tm_next
) {
137 tm_next
= LIST_NEXT(tm
, link
);
139 if (TIMEVAL_LEQ(tm
->tm
, now
)) {
140 if ((*tm
->expire
)(tm
->expire_data
) == NULL
)
141 continue; /* timer has been freed */
144 if (TIMEVAL_LT(tm
->tm
, tm_sentinel
))
145 tm_sentinel
= tm
->tm
;
148 if (TIMEVAL_EQUAL(tm_max
, tm_sentinel
)) {
149 /* no need to timeout */
151 } else if (TIMEVAL_LT(tm_sentinel
, now
)) {
152 /* this may occur when the interval is too small */
153 returnval
.tv_sec
= returnval
.tv_usec
= 0;
155 timeval_sub(&tm_sentinel
, &now
, &returnval
);
160 dhcp6_timer_rest(timer
)
161 struct dhcp6_timer
*timer
;
164 static struct timeval returnval
; /* XXX */
166 gettimeofday(&now
, NULL
);
167 if (TIMEVAL_LEQ(timer
->tm
, now
)) {
168 dprintf(LOG_DEBUG
, FNAME
,
169 "a timer must be expired, but not yet");
170 returnval
.tv_sec
= returnval
.tv_usec
= 0;
172 timeval_sub(&timer
->tm
, &now
, &returnval
);
179 timeval_add(a
, b
, result
)
180 struct timeval
*a
, *b
, *result
;
184 if ((l
= a
->tv_usec
+ b
->tv_usec
) < MILLION
) {
186 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
;
189 result
->tv_usec
= l
- MILLION
;
190 result
->tv_sec
= a
->tv_sec
+ b
->tv_sec
+ 1;
196 * XXX: this function assumes that a >= b.
199 timeval_sub(a
, b
, result
)
200 struct timeval
*a
, *b
, *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;