📄 timerd.c
字号:
long cur_sum, prev_sum; angel_Timer *tel; /* if no list, it's easy */ if (IsListEmpty(&angel_Active_Timers)) { this->delay = this->interval; /* LogInfo(LOG_TIMER, ("queueTimer: Add to EL (%d)\n", this->interval)); */ Timer_AddHead(&angel_Active_Timers, this); return; } /* if our interval is earliest of all list, it's easy too */ tel = Timer_FirstNode(&angel_Active_Timers); if (tel->delay >= this->interval) { /* our delay is simply our interval */ this->delay = this->interval; /* set the delay of the next to account for ours coming first */ tel->delay -= this->interval; /* LogInfo(LOG_TIMER, ("queueTimer: Add SOL (%d)\n", this->interval)); */ /* add ourselves at the list head */ Timer_AddHead(&angel_Active_Timers, this); return; } /* * must find out where to put new timer. Loop to find the first node * for which the interval is larger, calculating the sum of delays * for the previous and this node. * * almost invariant: cur_sum := prev_sum + tel->delay * [ not for first loop, but we have considered those cases anyway] * */ cur_sum = 0; prev_sum = 0; while(!Timer_AtEndOfList(tel)) { prev_sum = cur_sum; cur_sum += tel->delay; /* wait for a larger delay. If the delays are equal (that is, * cur_sum == this->interval) we intentionally put the newer * call after the older by advancing tel to the next node. */ if ( cur_sum > this->interval ) break; tel = Timer_Succ(tel); } LogInfo(LOG_TIMER, ("queueTimer: this %d cs %d, ps %d\n", this->interval, cur_sum, prev_sum)); /* * We insert *before* a node: if at end of list, there is no * before, so add at end. * * [I guess in theory InsertBefore can work with tel at eol but * this is a lot clearer -- ric] */ if (Timer_AtEndOfList(tel)) { /* if tel is at end, it exited the while loop without updating * prev_sum for the last node; hence we use cur_sum here, not * prev_sum */ this->delay = this->interval - cur_sum; LogInfo(LOG_TIMER, ("queueTimer: Add EOL: %d\n", this->delay)); /* add timer at end of list */ Timer_AddTail(&angel_Active_Timers, this); } else { /* * set the delay of the to-be-inserted node; prev_sum is the * sum up to the point we want to insert, so the delay from * there is easy: */ this->delay = this->interval - prev_sum; /* * add timer before 'tel' in list, adjusting tel's delay: * * cur_sum is the delay from now to the time tel fires. If * you subtract the new node's interval you get the delay * from this node to the next. */ tel->delay = cur_sum - this->interval; LogInfo(LOG_TIMER, ("queueTimer: Add MID: this->delay = %s, tel->delay = %d\n", this->delay, tel->delay)); /* Insert 'this' before 'tel' in list */ Timer_Insert(tel, this); }}/* * Function: Timer_DeleteTimer * * Purpose: Externally visible function to delete a * given timer. Passed the small integer timer * id, converts to a timer pointer and * passes it to timer_delTimer. * * Arguments: timer - the timer id. * * Return: none * * Pre-conditions: Timers initialised. * * Post-conditions: This timer deleted, if it was valid. * */void Timer_DeleteTimer(int timer){ angel_Timer *t = &angel_Timer_Pool[timer]; int s = Angel_TimerDev.timer_critical(); LogInfo(LOG_TIMER, ("DeleteTimer: timer %d\n", timer)); if (timer < MAX_TIMERS && (t->flags & TF_ALLOC)) { timer_delTimer(t); t->flags = 0; Timer_AddTail(&angel_Free_Timers, t); } Angel_TimerDev.timer_normal(s);}/* * Function: timer_delTimer * * Purpose: delete the given timer from the * timer list. It is more efficient * if the timer is the head element. * * * Arguments: t - pointer to a timer which should be * in the timer list. * * Return: none * * Pre-conditions: t must be part of the timer list and the * routine Timer_Initialise called. * * Post-conditions: t is no longer part of the timer * list; delays including 't' adjusted. * */static void timer_delTimer(angel_Timer *t){ /* * if the delay in t is non-zero, we must add * that delay to the next element in the * timer list, or it will happen t->delay ms * early. */ if (!Timer_AtEndOfList(t)) { angel_Timer *nt = Timer_Succ(t); if (t->delay) LogInfo(LOG_TIMER, ("delTimer: add delay %d to %d\n", t->delay, nt->delay)); nt->delay += t->delay; } /* * Remove t from the list. Calling code must add it * to free list if needed. */ Timer_Remove(t);}#endif /* defined(TEST) || TIMER_SUPPORTED *//**********************************************************************************//* test code for the above using Unix timers to simulate interrupt events. */#ifdef TEST#undef CLK_TCK#include <signal.h>#include <sys/time.h>static int unix_interval;#ifdef TEST_PRINTvoid timer_printList(char *str){ angel_Timer *tl = Timer_FirstNode(&angel_Active_Timers); printf(str); while(!Timer_AtEndOfList(tl)) { printf("[ i(%d) d(%d) %c%c%c ] ", tl->interval, tl->delay, tl->flags & TF_ALLOC ? 'A' : 'a', tl->flags & TF_SIGNALME ? 'S' : 's', tl->flags & TF_RELOAD ? 'R' : 'r'); tl = Timer_Succ(tl); } putchar('\n');}#endif /* TIMER_SUPPORTED */unix_sigalrm(){ Timer_Tick(0);}void unix_timer_init(){ struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_restorer = 0; if (sigaction(SIGALRM, &act, NULL) < 0) perror("sigact");}void unix_timer_stop(){ struct sigaction act; struct itimerval nextv; nextv.it_interval.tv_sec = 0; nextv.it_interval.tv_usec = 0; nextv.it_value = nextv.it_interval; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask,SIGALRM); act.sa_flags = 0; act.sa_restorer = 0; if (sigaction(SIGALRM, &act, NULL) < 0) perror("sigact"); if (setitimer(ITIMER_REAL, &nextv, NULL) < 0) perror("setitimer");}void unix_timer_start(){ struct itimerval nextv; struct sigaction act; act.sa_handler = (__sighandler_t)unix_sigalrm; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask,SIGALRM); act.sa_flags = 0; act.sa_restorer = 0; nextv.it_interval.tv_sec = 0; nextv.it_interval.tv_usec = unix_interval; nextv.it_value = nextv.it_interval; if (sigaction(SIGALRM, &act, NULL) < 0) perror("sigact"); if (setitimer(ITIMER_REAL, &nextv, NULL) < 0) perror("setitimer");}int unix_timer_critical(void){}void unix_timer_normal(int s){}void unix_timer_set_interval(long interval){ unix_interval = interval;}long unix_timer_get_interval(void){ return unix_interval;}const struct TimerDev Angel_TimerDev ={ unix_timer_init, unix_timer_start, unix_timer_stop, unix_timer_critical, unix_timer_normal, unix_timer_set_interval, unix_timer_get_interval};static void unix_event(int s){ printf("event %d signalled\n", s);}static int Angel_Signal(int t, int s){ printf("task %d signalled %d\n", t, s); return 0;}int main(int argc, char *argv[]){ int i; printf("Init\n"); Timer_Initialise(); printf("Start\n"); while(Timer_currentTime < 200) { } printf("Time: %d\n", Timer_currentTime); printf("Add timer -- 80ms, Signal, Reload\n"); i = Timer_NewTimer(80, TF_SIGNALME | TF_RELOAD, (TimerCallback)1, 2); printf("Got timer %d\n", i); while(Timer_currentTime < 500) { } printf("Del timer\n"); Timer_DeleteTimer(i); printf("Time: %d\n", Timer_currentTime); while(Timer_currentTime < 700) { } printf("Time: %d\n", Timer_currentTime); printf("Add timer -- 80ms, Signal, Reload\n"); i = Timer_NewTimer(80, TF_SIGNALME | TF_RELOAD, (TimerCallback)1, 2); printf("Got timer %d\n", i); printf("Add timer -- 200ms, Event, Reload\n"); i = Timer_NewTimer(200, TF_RELOAD, (TimerCallback)unix_event, 2); printf("Got timer %d\n", i); while(Timer_currentTime < 2000) { } printf("Time: %d\n", Timer_currentTime); printf("Stop\n");}#endif /* TEST *//**********************************************************************************//* EOF timer.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -