]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dope/server/common/tick.c
Inital import
[l4.git] / l4 / pkg / dope / server / common / tick.c
1 /*
2  * \brief   DOpE timer tick module
3  * \date    2004-04-7
4  * \author  Norman Feske <nf2@inf.tu-dresden.de>
5  */
6
7 /*
8  * Copyright (C) 2002-2004  Norman Feske  <nf2@os.inf.tu-dresden.de>
9  * Technische Universitaet Dresden, Operating Systems Research Group
10  *
11  * This file is part of the DOpE package, which is distributed under
12  * the  terms  of the  GNU General Public Licence 2.  Please see the
13  * COPYING file for details.
14  */
15
16 #include "dopestd.h"
17 #include "timer.h"
18 #include "tick.h"
19
20 #define MAX_TICKS 32
21
22 struct tick;
23 struct tick {
24         u32         deadline;            /* next deadline          */
25         u32         usec;                /* duration between ticks */
26         int       (*callback) (void *);  /* tick callback          */
27         void        *arg;                /* callback argument      */
28         struct tick *next;               /* next tick in ticklist  */
29 };
30
31 static struct tick ticks[MAX_TICKS];
32 static struct tick *head = NULL;     /* head of tick list */
33
34 static struct timer_services *timer;
35
36 int init_tick(struct dope_services *d);
37
38
39 /*************************
40  *** SERVICE FUNCTIONS ***
41  *************************/
42
43 /*** SCHEDULE NEW TICK EVENT ***/
44 static void queue_tick(struct tick *t) {
45         struct tick *curr;
46         
47         /* if ticklist is empty add first element */
48         if (!head) {
49                 t->next = 0;
50                 head    = t;
51                 return;
52         }
53
54         /* if deadline is smaller than any other deadline, put it on the head */
55         if (t->deadline < head->deadline) {
56                 t->next = head;
57                 head    = t;
58                 return;
59         }
60
61         /* find list element with a higher deadline */
62         curr = head;
63         while (curr->next && (curr->next->deadline < t->deadline)) curr = curr->next;
64
65         /* if end of list is reached, append new element */
66         if (!curr->next) {
67                 curr->next = t;
68                 return;
69         }
70
71         /* insert element in middle of list */
72         t->next    = curr->next;
73         curr->next = t;
74 }
75
76
77 /*** REGISTER NEW TIMER TICK CALLBACK ROUTINE ***
78  *
79  * \param msec      duration between ticks
80  * \param callback  routine that is called for every tick
81  * \param arg       private argument for callback
82  * \return          1 on success
83  *
84  * The return code of this function should be evaluated!
85  */
86 static int tick_add(s32 msec, int (*callback)(void *), void *arg) {
87         int i;
88
89         /* find empty tick slot */
90         for (i=0; i<MAX_TICKS; i++)
91                 if (ticks[i].callback == NULL) break;
92
93         /* no empty tick slot - return 0 */
94         if (i == MAX_TICKS) return 0;
95
96         /* put new tick at the beginning of the ticklist */
97         ticks[i].usec     = msec * 1000;
98         ticks[i].deadline = timer->get_time() + ticks[i].usec;
99         ticks[i].callback = callback;
100         ticks[i].arg      = arg;
101         queue_tick(&ticks[i]);
102
103         return 1;
104 }
105
106
107 /*** CHECK FOR DUE TICK EVENTS AND EXECUTE CALLBACKS ***/
108 static void tick_handle(void) {
109         u32 now = timer->get_time();
110         struct tick *curr = head;
111         
112         while ((curr = head) && ((s32)now > (s32)head->deadline)) {
113                 void *arg = head->arg;
114
115                 /* remove tick from head of the list */
116                 head = curr->next;
117                 curr->next = NULL;
118
119                 if (curr->callback(arg)) {
120                         /* tick is still valid - schedule next event */
121                         curr->deadline = now + curr->usec;
122                         queue_tick(curr);
123                 } else {
124                         /* mark tick slot as free */
125                         curr->callback = NULL;
126                 }
127         }
128 }
129
130
131 /****************************************
132  *** SERVICE STRUCTURE OF THIS MODULE ***
133  ****************************************/
134
135 static struct tick_services services = {
136         tick_add,
137         tick_handle,
138 };
139
140
141 /**************************
142  *** MODULE ENTRY POINT ***
143  **************************/
144
145 int init_tick(struct dope_services *dope) {
146
147         timer     = dope->get_module("Timer 1.0");
148         
149         dope->register_module("Tick 1.0",&services);
150         return 1;
151 }