2 * Copyright (c) 2003-2004 MontaVista Software, Inc.
3 * Copyright (c) 2006-2007 Red Hat, Inc.
7 * Author: Steven Dake (sdake@mvista.com)
9 * This software licensed under BSD license, the text of which follows:
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of the MontaVista Software, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
36 #ifndef TLIST_H_DEFINED
37 #define TLIST_H_DEFINED
44 #include <sys/param.h>
46 #include "../include/list.h"
49 #define HZ 100 /* 10ms */
53 typedef void * timer_handle
;
58 struct list_head timer_head
;
59 struct list_head
*timer_iter
;
62 struct timerlist_timer
{
63 struct list_head list
;
64 unsigned long long nano_from_epoch
;
65 void (*timer_fn
)(void *data
);
67 timer_handle handle_addr
;
70 static inline void timerlist_init (struct timerlist
*timerlist
)
72 list_init (&timerlist
->timer_head
);
75 static inline unsigned long long timerlist_nano_from_epoch (void)
77 unsigned long long nano_from_epoch
;
78 struct timeval time_from_epoch
;
79 gettimeofday (&time_from_epoch
, 0);
81 nano_from_epoch
= ((time_from_epoch
.tv_sec
* 1000000000ULL) + (time_from_epoch
.tv_usec
* 1000ULL));
82 return (nano_from_epoch
);
85 static inline void timerlist_add (struct timerlist
*timerlist
, struct timerlist_timer
*timer
)
87 struct list_head
*timer_list
= 0;
88 struct timerlist_timer
*timer_from_list
;
91 for (found
= 0, timer_list
= timerlist
->timer_head
.next
;
92 timer_list
!= &timerlist
->timer_head
;
93 timer_list
= timer_list
->next
) {
95 timer_from_list
= list_entry (timer_list
,
96 struct timerlist_timer
, list
);
98 if (timer_from_list
->nano_from_epoch
> timer
->nano_from_epoch
) {
99 list_add (&timer
->list
, timer_list
->prev
);
101 break; /* for timer iteration */
105 list_add (&timer
->list
, timerlist
->timer_head
.prev
);
109 static inline int timerlist_add_absolute (struct timerlist
*timerlist
,
110 void (*timer_fn
) (void *data
),
112 unsigned long long nano_from_epoch
,
113 timer_handle
*handle
)
115 struct timerlist_timer
*timer
;
117 timer
= (struct timerlist_timer
*)malloc (sizeof (struct timerlist_timer
));
123 timer
->nano_from_epoch
= nano_from_epoch
;
125 timer
->timer_fn
= timer_fn
;
126 timer
->handle_addr
= handle
;
127 timerlist_add (timerlist
, timer
);
133 static inline int timerlist_add_duration (struct timerlist
*timerlist
,
134 void (*timer_fn
) (void *data
),
136 unsigned long long nano_duration
,
137 timer_handle
*handle
)
139 struct timerlist_timer
*timer
;
141 timer
= (struct timerlist_timer
*)malloc (sizeof (struct timerlist_timer
));
147 timer
->nano_from_epoch
= timerlist_nano_from_epoch() + nano_duration
;
149 timer
->timer_fn
= timer_fn
;
150 timer
->handle_addr
= handle
;
151 timerlist_add (timerlist
, timer
);
157 static inline void timerlist_del (struct timerlist
*timerlist
, timer_handle timer_handle
)
159 struct timerlist_timer
*timer
= (struct timerlist_timer
*)timer_handle
;
161 memset (timer
->handle_addr
, 0, sizeof (struct timerlist_timer
*));
163 * If the next timer after the currently expiring timer because
164 * timerlist_del is called from a timer handler, get to the next
167 if (timerlist
->timer_iter
== &timer
->list
) {
168 timerlist
->timer_iter
= timerlist
->timer_iter
->next
;
170 list_del (&timer
->list
);
171 list_init (&timer
->list
);
175 static inline void timerlist_pre_dispatch (struct timerlist
*timerlist
, timer_handle timer_handle
)
177 struct timerlist_timer
*timer
= (struct timerlist_timer
*)timer_handle
;
179 memset (timer
->handle_addr
, 0, sizeof (struct timerlist_timer
*));
180 list_del (&timer
->list
);
181 list_init (&timer
->list
);
184 static inline void timerlist_post_dispatch (struct timerlist
*timerlist
, timer_handle timer_handle
)
186 struct timerlist_timer
*timer
= (struct timerlist_timer
*)timer_handle
;
192 * returns the number of msec until the next timer will expire for use with poll
194 static inline unsigned long long timerlist_msec_duration_to_expire (struct timerlist
*timerlist
)
196 struct timerlist_timer
*timer_from_list
;
197 volatile unsigned long long nano_from_epoch
;
198 volatile unsigned long long msec_duration_to_expire
;
201 * empty list, no expire
203 if (timerlist
->timer_head
.next
== &timerlist
->timer_head
) {
207 timer_from_list
= list_entry (timerlist
->timer_head
.next
,
208 struct timerlist_timer
, list
);
210 nano_from_epoch
= timerlist_nano_from_epoch();
213 * timer at head of list is expired, zero msecs required
215 if (timer_from_list
->nano_from_epoch
< nano_from_epoch
) {
220 msec_duration_to_expire
= ((timer_from_list
->nano_from_epoch
- nano_from_epoch
) / 1000000ULL) +
222 return (msec_duration_to_expire
);
226 * Expires any timers that should be expired
228 static inline void timerlist_expire (struct timerlist
*timerlist
)
230 struct timerlist_timer
*timer_from_list
;
231 unsigned long long nano_from_epoch
;
233 nano_from_epoch
= timerlist_nano_from_epoch();
235 for (timerlist
->timer_iter
= timerlist
->timer_head
.next
;
236 timerlist
->timer_iter
!= &timerlist
->timer_head
;) {
238 timer_from_list
= list_entry (timerlist
->timer_iter
,
239 struct timerlist_timer
, list
);
241 if (timer_from_list
->nano_from_epoch
< nano_from_epoch
) {
242 timerlist
->timer_iter
= timerlist
->timer_iter
->next
;
244 timerlist_pre_dispatch (timerlist
, timer_from_list
);
246 timer_from_list
->timer_fn (timer_from_list
->data
);
248 timerlist_post_dispatch (timerlist
, timer_from_list
);
250 break; /* for timer iteration */
253 timerlist
->timer_iter
= 0;
255 #endif /* TLIST_H_DEFINED */