1 #include "common.h" 2 3 #include <ddekit/memory.h> 4 #include <ddekit/semaphore.h> 5 #include <ddekit/thread.h> 6 #include <ddekit/timer.h> 7 8 #ifdef DDEBUG_LEVEL_TIMER 9 #undef DDEBUG 10 #define DDEBUG DDEBUG_LEVEL_TIMER 11 #endif 12 13 #include "debug.h" 14 #include "thread.h" 15 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) 19 20 typedef clock_t myclock_t; 21 22 struct ddekit_timer_s { 23 void (*fn)(void *); 24 void *args; 25 int id; 26 myclock_t exp; 27 struct ddekit_timer_s * next; 28 }; 29 30 31 static ddekit_sem_t *pending_timer_ints; 32 33 /* are we currently expecting a alarm notify? */ 34 int _ddekit_timer_pending = 0; 35 36 unsigned long long jiffies; 37 unsigned long HZ; 38 39 static struct ddekit_timer_s list = {0,0,-1,1,0}; 40 static int _id = 0 ; 41 static ddekit_thread_t *th; 42 static ddekit_lock_t lock; 43 44 static void lock_timer(void); 45 static void unlock_timer(void); 46 static clock_t get_current_clock(void); 47 static void remove_timer(int id); 48 static int insert_timer(struct ddekit_timer_s *t); 49 static struct ddekit_timer_s * get_next( myclock_t exp ); 50 static void ddekit_timer_thread(void *data); 51 52 /**************************************************************************** 53 * Private funtions * 54 ****************************************************************************/ 55 56 /***************************************************************************** 57 * lock_timer * 58 ****************************************************************************/ 59 static void lock_timer() 60 { 61 ddekit_lock_lock(&lock); 62 } 63 64 /***************************************************************************** 65 * unlock_timer * 66 ****************************************************************************/ 67 static void unlock_timer() 68 { 69 ddekit_lock_unlock(&lock); 70 } 71 72 /***************************************************************************** 73 * get_current_clock * 74 ****************************************************************************/ 75 static myclock_t get_current_clock() 76 { 77 /* returns the current clock tick */ 78 myclock_t ret; 79 getticks(&ret); 80 return ret; 81 } 82 83 /***************************************************************************** 84 * remove_timer * 85 ****************************************************************************/ 86 static void remove_timer(int id) 87 { 88 /* removes a timer from the timer list */ 89 struct ddekit_timer_s *l,*m; 90 91 lock_timer(); 92 93 for (l = &list; l && l->next && l->next->id!=id; l = l->next ) 94 ; 95 96 if (l && l->next) { 97 m = l->next; 98 99 DDEBUG_MSG_VERBOSE( 100 "deleting timer at for tick: %d fn: %p, (now: %d)\n", 101 m->exp, m->fn, jiffies); 102 103 l->next = m->next; 104 DDEBUG_MSG_TIMER(m); 105 106 ddekit_simple_free(m); 107 } 108 109 unlock_timer(); 110 } 111 112 /***************************************************************************** 113 * insert_timer * 114 ****************************************************************************/ 115 static int insert_timer(struct ddekit_timer_s *t) 116 { 117 /* inserts a timer to the timer list */ 118 int ret; 119 120 lock_timer(); 121 122 struct ddekit_timer_s *l; 123 124 for (l = &list; l->next && l->next->exp <= t->exp; l = l->next) { 125 126 } 127 128 t->next = l->next; 129 l->next = t; 130 131 t->id = ret = _id; 132 133 _id++; 134 135 if (_id==0) { 136 DDEBUG_MSG_WARN("Timer ID overflow..."); 137 } 138 139 DDEBUG_MSG_TIMER(t); 140 141 unlock_timer(); 142 143 return ret; 144 } 145 146 /***************************************************************************** 147 * get_next * 148 ****************************************************************************/ 149 static struct ddekit_timer_s * get_next( myclock_t exp ) 150 { 151 /* 152 * this one get the next timer, which's timeout expired, 153 * returns NULL if no timer is pending 154 */ 155 struct ddekit_timer_s * ret = 0; 156 lock_timer(); 157 if (list.next) 158 { 159 if (list.next->exp <= exp) 160 { 161 ret = list.next; 162 list.next = ret->next; 163 } 164 } 165 unlock_timer(); 166 return ret; 167 } 168 169 /***************************************************************************** 170 * ddekit_timer_thread * 171 ****************************************************************************/ 172 static void ddekit_timer_thread(void * data) 173 { 174 struct ddekit_timer_s * l; 175 176 /* rock around the clock! */ 177 for ( ; ; ) 178 { 179 /* wait for timer interrupts */ 180 ddekit_sem_down(pending_timer_ints); 181 DDEBUG_MSG_VERBOSE("handling timer interrupt"); 182 183 /* execute all expired timers */ 184 while( (l = get_next(jiffies)) != 0 ) { 185 DDEBUG_MSG_TIMER(l); 186 if (l->fn) { 187 l->fn(l->args); 188 } 189 ddekit_simple_free(l); 190 } 191 } 192 } 193 194 195 /**************************************************************************** 196 * Public functions (ddekit/timer.h) * 197 ****************************************************************************/ 198 199 /***************************************************************************** 200 * ddekit_add_timer * 201 ****************************************************************************/ 202 int ddekit_add_timer 203 (void (*fn)(void *), void *args, unsigned long timeout) 204 { 205 struct ddekit_timer_s *t; 206 207 t = (struct ddekit_timer_s *) 208 ddekit_simple_malloc(sizeof(struct ddekit_timer_s )); 209 210 t->fn = fn; 211 t->args = args; 212 t->exp = (myclock_t) timeout; 213 214 return insert_timer(t); 215 } 216 217 /***************************************************************************** 218 * ddekit_del_timer * 219 ****************************************************************************/ 220 int ddekit_del_timer(int timer) 221 { 222 remove_timer(timer); 223 return 0; 224 } 225 226 /***************************************************************************** 227 * ddekit_timer_pending * 228 ****************************************************************************/ 229 int ddekit_timer_pending(int timer) 230 { 231 int ret=0; 232 struct ddekit_timer_s *t; 233 lock_timer(); 234 for (t=list.next; t; t = t->next) { 235 if (t->id==timer) { 236 ret = 1; 237 } 238 239 } 240 unlock_timer(); 241 return ret; 242 } 243 244 /***************************************************************************** 245 * ddekit_init_timers * 246 ****************************************************************************/ 247 void ddekit_init_timers(void) 248 { 249 static int first_time=0; 250 251 if (!first_time) 252 { 253 ddekit_lock_init(&lock); 254 jiffies = get_current_clock(); 255 HZ = sys_hz(); 256 pending_timer_ints = ddekit_sem_init(0); 257 th = ddekit_thread_create(ddekit_timer_thread, 0, "timer"); 258 first_time=1; 259 DDEBUG_MSG_INFO("DDEkit timer subsustem initialized"); 260 } 261 } 262 263 /***************************************************************************** 264 * ddekit_get_timer_thread * 265 ****************************************************************************/ 266 ddekit_thread_t *ddekit_get_timer_thread(void) 267 { 268 return th; 269 } 270 271 /**************************************************************************** 272 * ddekit_internal (src/timer.h) * 273 ****************************************************************************/ 274 275 /***************************************************************************** 276 * _ddekit_timer_interrupt * 277 ****************************************************************************/ 278 void _ddekit_timer_interrupt(void) 279 { 280 jiffies = get_current_clock(); 281 DDEBUG_MSG_VERBOSE("now: %d", jiffies); 282 ddekit_sem_up(pending_timer_ints); 283 } 284 285 /***************************************************************************** 286 * _ddekit_timer_update * 287 ****************************************************************************/ 288 void _ddekit_timer_update() 289 { 290 lock_timer(); 291 292 static myclock_t next_timout; 293 if(list.next) 294 { 295 if(!_ddekit_timer_pending || list.next->exp < next_timout) { 296 297 unsigned to = list.next->exp - jiffies; 298 299 _ddekit_timer_pending = 1; 300 301 if (list.next->exp <= jiffies) { 302 DDEBUG_MSG_WARN("Timeout lies in past to %d, now: %d", 303 list.next->exp, jiffies); 304 to = 1; 305 } 306 307 sys_setalarm(to, 0 /* REL */); 308 309 DDEBUG_MSG_VERBOSE("requesting alarm for clock tick %d , now %d", 310 list.next->exp, jiffies); 311 } 312 next_timout = list.next->exp; 313 } 314 unlock_timer(); 315 } 316