3 #include <ddekit/memory.h>
4 #include <ddekit/semaphore.h>
5 #include <ddekit/thread.h>
6 #include <ddekit/timer.h>
8 #ifdef DDEBUG_LEVEL_TIMER
10 #define DDEBUG DDEBUG_LEVEL_TIMER
16 #define DDEBUG_MSG_TIMER(t) \
17 DDEBUG_MSG_VERBOSE("id: %d, exp: %d, fn: %d, now %d", \
18 (t)->id, (t)->exp, (t)->fn, jiffies)
20 typedef clock_t myclock_t
;
22 struct ddekit_timer_s
{
27 struct ddekit_timer_s
* next
;
31 static ddekit_sem_t
*pending_timer_ints
;
33 /* are we currently expecting a alarm notify? */
34 int _ddekit_timer_pending
= 0;
36 unsigned long long jiffies
;
39 static struct ddekit_timer_s list
= {0,0,-1,1,0};
41 static ddekit_thread_t
*th
;
42 static ddekit_lock_t lock
;
44 static void lock_timer(void);
45 static void unlock_timer(void);
46 static void remove_timer(int id
);
47 static int insert_timer(struct ddekit_timer_s
*t
);
48 static struct ddekit_timer_s
* get_next( myclock_t exp
);
49 static void ddekit_timer_thread(void *data
);
51 /****************************************************************************
53 ****************************************************************************/
55 /*****************************************************************************
57 ****************************************************************************/
58 static void lock_timer()
60 ddekit_lock_lock(&lock
);
63 /*****************************************************************************
65 ****************************************************************************/
66 static void unlock_timer()
68 ddekit_lock_unlock(&lock
);
71 /*****************************************************************************
73 ****************************************************************************/
74 static void remove_timer(int id
)
76 /* removes a timer from the timer list */
77 struct ddekit_timer_s
*l
,*m
;
81 for (l
= &list
; l
&& l
->next
&& l
->next
->id
!=id
; l
= l
->next
)
88 "deleting timer at for tick: %d fn: %p, (now: %d)\n",
89 m
->exp
, m
->fn
, jiffies
);
94 ddekit_simple_free(m
);
100 /*****************************************************************************
102 ****************************************************************************/
103 static int insert_timer(struct ddekit_timer_s
*t
)
105 /* inserts a timer to the timer list */
110 struct ddekit_timer_s
*l
;
112 for (l
= &list
; l
->next
&& l
->next
->exp
<= t
->exp
; l
= l
->next
) {
124 DDEBUG_MSG_WARN("Timer ID overflow...");
134 /*****************************************************************************
136 ****************************************************************************/
137 static struct ddekit_timer_s
* get_next( myclock_t exp
)
140 * this one get the next timer, which's timeout expired,
141 * returns NULL if no timer is pending
143 struct ddekit_timer_s
* ret
= 0;
147 if (list
.next
->exp
<= exp
)
150 list
.next
= ret
->next
;
157 /*****************************************************************************
158 * ddekit_timer_thread *
159 ****************************************************************************/
160 static void ddekit_timer_thread(void * data
)
162 struct ddekit_timer_s
* l
;
164 /* rock around the clock! */
167 /* wait for timer interrupts */
168 ddekit_sem_down(pending_timer_ints
);
169 DDEBUG_MSG_VERBOSE("handling timer interrupt");
171 /* execute all expired timers */
172 while( (l
= get_next(jiffies
)) != 0 ) {
177 ddekit_simple_free(l
);
183 /****************************************************************************
184 * Public functions (ddekit/timer.h) *
185 ****************************************************************************/
187 /*****************************************************************************
189 ****************************************************************************/
191 (void (*fn
)(void *), void *args
, unsigned long timeout
)
193 struct ddekit_timer_s
*t
;
195 t
= (struct ddekit_timer_s
*)
196 ddekit_simple_malloc(sizeof(struct ddekit_timer_s
));
200 t
->exp
= (myclock_t
) timeout
;
202 return insert_timer(t
);
205 /*****************************************************************************
207 ****************************************************************************/
208 int ddekit_del_timer(int timer
)
214 /*****************************************************************************
215 * ddekit_timer_pending *
216 ****************************************************************************/
217 int ddekit_timer_pending(int timer
)
220 struct ddekit_timer_s
*t
;
222 for (t
=list
.next
; t
; t
= t
->next
) {
232 /*****************************************************************************
233 * ddekit_init_timers *
234 ****************************************************************************/
235 void ddekit_init_timers(void)
237 static int first_time
=0;
241 ddekit_lock_init(&lock
);
242 jiffies
= getticks();
244 pending_timer_ints
= ddekit_sem_init(0);
245 th
= ddekit_thread_create(ddekit_timer_thread
, 0, "timer");
247 DDEBUG_MSG_INFO("DDEkit timer subsustem initialized");
251 /*****************************************************************************
252 * ddekit_get_timer_thread *
253 ****************************************************************************/
254 ddekit_thread_t
*ddekit_get_timer_thread(void)
259 /****************************************************************************
260 * ddekit_internal (src/timer.h) *
261 ****************************************************************************/
263 /*****************************************************************************
264 * _ddekit_timer_interrupt *
265 ****************************************************************************/
266 void _ddekit_timer_interrupt(void)
268 jiffies
= getticks();
269 DDEBUG_MSG_VERBOSE("now: %d", jiffies
);
270 ddekit_sem_up(pending_timer_ints
);
273 /*****************************************************************************
274 * _ddekit_timer_update *
275 ****************************************************************************/
276 void _ddekit_timer_update()
280 static myclock_t next_timout
;
283 if(!_ddekit_timer_pending
|| list
.next
->exp
< next_timout
) {
285 unsigned to
= list
.next
->exp
- jiffies
;
287 _ddekit_timer_pending
= 1;
289 if (list
.next
->exp
<= jiffies
) {
290 DDEBUG_MSG_WARN("Timeout lies in past to %d, now: %d",
291 list
.next
->exp
, jiffies
);
295 sys_setalarm(to
, 0 /* REL */);
297 DDEBUG_MSG_VERBOSE("requesting alarm for clock tick %d , now %d",
298 list
.next
->exp
, jiffies
);
300 next_timout
= list
.next
->exp
;