timer.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:6k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* General purpose software timer facilities
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "proc.h"
  8. #include "mbuf.h"
  9. #include "commands.h"
  10. #include "daemon.h"
  11. #include "hardware.h"
  12. #include "socket.h"
  13. /* Head of running timer chain.
  14.  * The list of running timers is sorted in increasing order of expiration;
  15.  * i.e., the first timer to expire is always at the head of the list.
  16.  */
  17. static struct timer *Timers;
  18. static void t_alarm(void *x);
  19. /* Process that handles clock ticks */
  20. void
  21. timerproc(i,v1,v2)
  22. int i;
  23. void *v1,*v2;
  24. {
  25. register struct timer *t;
  26. register struct timer *expired;
  27. void (**vf)(void);
  28. int i_state;
  29. int tmp;
  30. int32 clock;
  31. for(;;){
  32. /* Atomic read and decrement of Tick */
  33. for(;;){
  34. i_state = dirps();
  35. tmp = Tick;
  36. if(tmp != 0){
  37. Tick--;
  38. restore(i_state);
  39. break;
  40. }
  41. restore(i_state);
  42. kwait(&Tick);
  43. }
  44. if(!istate()){
  45. restore(1);
  46. printf("timer: ints were off!n");
  47. }
  48. /* Call the functions listed in config.c */
  49. for(vf = Cfunc;*vf != NULL;vf++)
  50. (*vf)();
  51. kwait(NULL); /* Let them all do their writes */
  52. if(Timers == NULL)
  53. continue; /* No active timers, all done */
  54. /* Initialize null expired timer list */
  55. expired = NULL;
  56. clock = rdclock();
  57. /* Move expired timers to expired list. Note use of
  58.  * subtraction and comparison to zero rather than the
  59.  * more obvious simple comparison; this avoids
  60.  * problems when the clock count wraps around.
  61.  */
  62. while(Timers != NULL && (clock - Timers->expiration) >= 0){
  63. if(Timers->next == Timers){
  64. printf("PANIC: Timer loop at %lxn",
  65.  (long)Timers);
  66. iostop();
  67. exit(1);
  68. }
  69. /* Save Timers since stop_timer will change it */
  70. t = Timers;
  71. stop_timer(t);
  72. t->state = TIMER_EXPIRE;
  73. /* Add to expired timer list */
  74. t->next = expired;
  75. expired = t;
  76. }
  77. /* Now go through the list of expired timers, removing each
  78.  * one and kicking the notify function, if there is one
  79.  */
  80. while((t = expired) != NULL){
  81. expired = t->next;
  82. if(t->func){
  83. (*t->func)(t->arg);
  84. }
  85. }
  86. kwait(NULL); /* Let them run before handling more ticks */
  87. }
  88. }
  89. /* Start a timer */
  90. void
  91. start_timer(t)
  92. struct timer *t;
  93. {
  94. register struct timer *tnext;
  95. struct timer *tprev = NULL;
  96. if(t == NULL)
  97. return;
  98. if(t->state == TIMER_RUN)
  99. stop_timer(t);
  100. if(t->duration == 0)
  101. return; /* A duration value of 0 disables the timer */
  102. t->expiration = rdclock() + t->duration;
  103. t->state = TIMER_RUN;
  104. /* Find right place on list for this guy. Once again, note use
  105.  * of subtraction and comparison with zero rather than direct
  106.  * comparison of expiration times.
  107.  */
  108. for(tnext = Timers;tnext != NULL;tprev=tnext,tnext = tnext->next){
  109. if((tnext->expiration - t->expiration) >= 0)
  110. break;
  111. }
  112. /* At this point, tprev points to the entry that should go right
  113.  * before us, and tnext points to the entry just after us. Either or
  114.  * both may be null.
  115.  */
  116. if(tprev == NULL)
  117. Timers = t; /* Put at beginning */
  118. else
  119. tprev->next = t;
  120. t->next = tnext;
  121. }
  122. /* Stop a timer */
  123. void
  124. stop_timer(timer)
  125. struct timer *timer;
  126. {
  127. register struct timer *t;
  128. struct timer *tlast = NULL;
  129. if(timer == NULL || timer->state != TIMER_RUN)
  130. return;
  131. /* Verify that timer is really on list */
  132. for(t = Timers;t != NULL;tlast = t,t = t->next)
  133. if(t == timer)
  134. break;
  135. if(t == NULL)
  136. return; /* Should probably panic here */
  137. /* Delete from active timer list */
  138. if(tlast != NULL)
  139. tlast->next = t->next;
  140. else
  141. Timers = t->next; /* Was first on list */
  142. t->state = TIMER_STOP;
  143. }
  144. /* Return milliseconds remaining on this timer */
  145. int32
  146. read_timer(t)
  147. struct timer *t;
  148. {
  149. int32 remaining;
  150. if(t == NULL || t->state != TIMER_RUN)
  151. return 0;
  152. remaining = t->expiration - rdclock();
  153. if(remaining <= 0)
  154. return 0; /* Already expired */
  155. else
  156. return remaining * MSPTICK;
  157. }
  158. void
  159. set_timer(t,interval)
  160. struct timer *t;
  161. int32 interval;
  162. {
  163. if(t == NULL)
  164. return;
  165. /* Round the interval up to the next full tick, and then
  166.  * add another tick to guarantee that the timeout will not
  167.  * occur before the interval is up. This is necessary because
  168.  * we're asynchronous with the system clock.
  169.  */
  170. if(interval != 0)
  171. t->duration = 1 + (interval + MSPTICK - 1)/MSPTICK;
  172. else
  173. t->duration = 0;
  174. }
  175. /* Delay process for specified number of milliseconds.
  176.  * Normally returns 0; returns -1 if aborted by alarm.
  177.  */
  178. int
  179. ppause(ms)
  180. int32 ms;
  181. {
  182. int val;
  183. if(Curproc == NULL || ms == 0)
  184. return 0;
  185. kalarm(ms);
  186. /* The actual event doesn't matter, since we'll be alerted */
  187. while(Curproc->alarm.state == TIMER_RUN){
  188. if((val = kwait(Curproc)) != 0)
  189. break;
  190. }
  191. kalarm(0L); /* Make sure it's stopped, in case we were killed */
  192. return (val == EALARM) ? 0 : -1;
  193. }
  194. static void
  195. t_alarm(x)
  196. void *x;
  197. {
  198. alert((struct proc *)x,EALARM);
  199. }
  200. /* Send signal to current process after specified number of milliseconds */
  201. void
  202. kalarm(ms)
  203. int32 ms;
  204. {
  205. if(Curproc != NULL){
  206. set_timer(&Curproc->alarm,ms);
  207. Curproc->alarm.func = t_alarm;
  208. Curproc->alarm.arg = (char *)Curproc;
  209. start_timer(&Curproc->alarm);
  210. }
  211. }
  212. /* Convert time count in seconds to printable days:hr:min:sec format */
  213. char *
  214. tformat(t)
  215. int32 t;
  216. {
  217. static char buf[17],*cp;
  218. unsigned int days,hrs,mins,secs;
  219. int minus;
  220. if(t < 0){
  221. t = -t;
  222. minus = 1;
  223. } else
  224. minus = 0;
  225. secs = t % 60;
  226. t /= 60;
  227. mins = t % 60;
  228. t /= 60;
  229. hrs = t % 24;
  230. t /= 24;
  231. days = t;
  232. if(minus){
  233. cp = buf+1;
  234. buf[0] = '-';
  235. } else
  236. cp = buf;
  237. sprintf(cp,"%u:%02u:%02u:%02u",days,hrs,mins,secs);
  238. return buf;
  239. }