timer.c revision 6735
1/* 2 * PPP Timer Processing Module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id:$ 21 * 22 * TODO: 23 */ 24#include "defs.h" 25#include <sys/time.h> 26#include <signal.h> 27#include "timeout.h" 28#ifdef SIGALRM 29#include <errno.h> 30#endif 31void StopTimerNoBlock( struct pppTimer *); 32void ShowTimers(void); 33 34void 35StopTimer( struct pppTimer *tp ) 36{ 37#ifdef SIGALRM 38 int omask; 39 omask = sigblock(sigmask(SIGALRM)); 40#endif 41 StopTimerNoBlock(tp); 42#ifdef SIGALRM 43 sigsetmask(omask); 44#endif 45} 46void 47StartTimer(tp) 48struct pppTimer *tp; 49{ 50 struct pppTimer *t, *pt; 51 u_long ticks = 0; 52 53#ifdef SIGALRM 54 int omask; 55 omask = sigblock(sigmask(SIGALRM)); 56#endif 57 58 if (tp->state != TIMER_STOPPED) { 59 StopTimerNoBlock(tp); 60 } 61 if (tp->load == 0) { 62#ifdef DEBUG 63 logprintf("timer %x has 0 load!\n", tp); 64#endif 65 sigsetmask(omask); 66 return; 67 } 68 pt = NULL; 69 for (t = TimerList; t; t = t->next) { 70#ifdef DEBUG 71 logprintf("StartTimer: %x(%d): ticks: %d, rest: %d\n", t, t->state, ticks, t->rest); 72#endif 73 if (ticks + t->rest >= tp->load) 74 break; 75 ticks += t->rest; 76 pt = t; 77 } 78 79 tp->state = TIMER_RUNNING; 80 tp->rest = tp->load - ticks; 81#ifdef DEBUG 82 logprintf("Inserting %x before %x, rest = %d\n", tp, t, tp->rest); 83#endif 84 /* Insert given *tp just before *t */ 85 tp->next = t; 86 if (pt) { 87 pt->next = tp; 88 } else 89 TimerList = tp; 90 if (t) 91 t->rest -= tp->rest; 92 93#ifdef SIGALRM 94 sigsetmask(omask); 95#endif 96} 97 98void 99StopTimerNoBlock(tp) 100struct pppTimer *tp; 101{ 102 struct pppTimer *t, *pt; 103 104 /* 105 * A Running Timer should be removing TimerList, 106 * But STOPPED/EXPIRED is already removing TimerList. 107 * So just marked as TIMER_STOPPED. 108 * Do not change tp->enext!! (Might be Called by expired proc) 109 */ 110#ifdef DEBUG 111 logprintf("StopTimer: %x, next = %x state=%x\n", tp, tp->next, tp->state); 112#endif 113 if (tp->state != TIMER_RUNNING) { 114 tp->next = NULL; 115 tp->state = TIMER_STOPPED; 116 return; 117 } 118 119 pt = NULL; 120 for (t = TimerList; t != tp && t !=NULL ; t = t->next) 121 pt = t; 122 if (t) { 123 if (pt) 124 pt->next = t->next; 125 else 126 TimerList = t->next; 127 if (t->next) 128 t->next->rest += tp->rest; 129 } else { 130 logprintf("Oops, timer not found!!\n"); 131 } 132 tp->next = NULL; 133 tp->state = TIMER_STOPPED; 134} 135 136void 137TimerService() 138{ 139 struct pppTimer *tp, *exp, *wt; 140 141#ifdef DEBUG 142 ShowTimers(); 143#endif 144 if (tp = TimerList) { 145 tp->rest--; 146 if (tp->rest == 0) { 147 /* 148 * Multiple timers may expires at once. Create list of expired timers. 149 */ 150 exp = NULL; 151 do { 152 tp->state = TIMER_EXPIRED; 153 wt = tp->next; 154 tp->enext = exp; 155 exp = tp; 156#ifdef DEBUG 157 logprintf("Add %x to exp\n", tp); 158#endif 159 tp = wt; 160 } while (tp && (tp->rest == 0)); 161 162 TimerList = tp; 163#ifdef DEBUG 164 logprintf("TimerService: next is %x(%d)\n", 165 TimerList, TimerList? TimerList->rest : 0); 166#endif 167 /* 168 * Process all expired timers. 169 */ 170 while (exp) { 171#ifdef notdef 172 StopTimer(exp); 173#endif 174 if (exp->func) 175 (*exp->func)(exp->arg); 176 /* 177 * Just Removing each item from expired list 178 * And exp->enext will be intialized at next expire 179 * in this funtion. 180 */ 181 exp = exp->enext; 182 } 183 } 184 } 185} 186 187void 188ShowTimers() 189{ 190 struct pppTimer *pt; 191 192 logprintf("---- Begin of Timer Service List---\n"); 193 for (pt = TimerList; pt; pt = pt->next) 194 logprintf("%x: load = %d, rest = %d, state =%x\n", 195 pt, pt->load, pt->rest, pt->state); 196 logprintf("---- End of Timer Service List ---\n"); 197} 198 199#ifdef SIGALRM 200u_int sleep( u_int sec ) 201{ 202 struct timeval to,st,et; 203 long sld, nwd, std; 204 205 gettimeofday( &st, NULL ); 206 to.tv_sec = sec; 207 to.tv_usec = 0; 208 std = st.tv_sec * 1000000 + st.tv_usec; 209 for (;;) { 210 if ( select ( 0, NULL, NULL, NULL, &to) == 0 || 211 errno != EINTR ) { 212 break; 213 } else { 214 gettimeofday( &et, NULL ); 215 sld = to.tv_sec * 1000000 + to.tv_sec; 216 nwd = et.tv_sec * 1000000 + et.tv_usec - std; 217 if ( sld > nwd ) 218 sld -= nwd; 219 else 220 sld = 1; /* Avoid both tv_sec/usec is 0 */ 221 222 /* Calculate timeout value for select */ 223 to.tv_sec = sld / 1000000; 224 to.tv_usec = sld % 1000000; 225 226 /* Forwarding signal as normal */ 227 kill(getpid(), SIGALRM); 228 } 229 } 230} 231 232void usleep( u_int usec) 233{ 234 struct timeval to,st,et; 235 long sld, nwd, std; 236 237 gettimeofday( &st, NULL ); 238 to.tv_sec = 0; 239 to.tv_usec = usec; 240 std = st.tv_sec * 1000000 + st.tv_usec; 241 for (;;) { 242 if ( select ( 0, NULL, NULL, NULL, &to) == 0 || 243 errno != EINTR ) { 244 break; 245 } else { 246 gettimeofday( &et, NULL ); 247 sld = to.tv_sec * 1000000 + to.tv_sec; 248 nwd = et.tv_sec * 1000000 + et.tv_usec - std; 249 if ( sld > nwd ) 250 sld -= nwd; 251 else 252 sld = 1; /* Avoid both tv_sec/usec is 0 */ 253 254 /* Calculate timeout value for select */ 255 to.tv_sec = sld / 1000000; 256 to.tv_usec = sld % 1000000; 257 258 /* Forwarding signal as normal */ 259 kill(getpid(), SIGALRM); 260 } 261 } 262} 263#endif 264