1 # include "sendmail.h" 2 3 SCCSID(@(#)clock.c 3.5 08/15/82); 4 5 /* 6 ** SETEVENT -- set an event to happen at a specific time. 7 ** 8 ** Parameters: 9 ** intvl -- intvl until next event occurs. 10 ** func -- function to call on event. 11 ** arg -- argument to func on event. 12 ** 13 ** Returns: 14 ** none. 15 ** 16 ** Side Effects: 17 ** none. 18 */ 19 20 EVENT * 21 setevent(intvl, func, arg) 22 time_t intvl; 23 int (*func)(); 24 int arg; 25 { 26 register EVENT **evp; 27 register EVENT *ev; 28 auto time_t now; 29 extern tick(); 30 31 # ifdef DEBUG 32 if (intvl <= 0) 33 { 34 syserr("setevent: intvl=%ld\n", intvl); 35 return; 36 } 37 # endif DEBUG 38 39 (void) time(&now); 40 41 /* search event queue for correct position */ 42 for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 43 { 44 if (ev->ev_time >= now + intvl) 45 break; 46 } 47 48 /* insert new event */ 49 ev = (EVENT *) xalloc(sizeof *ev); 50 ev->ev_time = now + intvl; 51 ev->ev_func = func; 52 ev->ev_arg = arg; 53 ev->ev_link = *evp; 54 *evp = ev; 55 56 /* reschedule next clock tick if appropriate */ 57 if (ev == EventQueue) 58 { 59 /* we have a new event */ 60 (void) signal(SIGALRM, tick); 61 (void) alarm(intvl); 62 } 63 64 # ifdef DEBUG 65 if (tTd(5, 2)) 66 printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 67 intvl, now + intvl, func, arg, ev); 68 # endif DEBUG 69 70 return (ev); 71 } 72 /* 73 ** CLREVENT -- remove an event from the event queue. 74 ** 75 ** Parameters: 76 ** ev -- pointer to event to remove. 77 ** 78 ** Returns: 79 ** none. 80 ** 81 ** Side Effects: 82 ** arranges for event ev to not happen. 83 */ 84 85 clrevent(ev) 86 register EVENT *ev; 87 { 88 register EVENT **evp; 89 90 # ifdef DEBUG 91 if (tTd(5, 2)) 92 printf("clrevent: ev=%x\n", ev); 93 # endif DEBUG 94 if (ev == NULL) 95 return; 96 97 /* find the parent event */ 98 for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 99 { 100 if (*evp == ev) 101 break; 102 } 103 104 /* now remove it */ 105 if (*evp == NULL) 106 { 107 /* hmmmmm.... must have happened. */ 108 return; 109 } 110 111 *evp = ev->ev_link; 112 free(ev); 113 } 114 /* 115 ** TICK -- take a clock tick 116 ** 117 ** Called by the alarm clock. This routine runs events as needed. 118 ** 119 ** Parameters: 120 ** none. 121 ** 122 ** Returns: 123 ** none. 124 ** 125 ** Side Effects: 126 ** calls the next function in EventQueue. 127 */ 128 129 tick() 130 { 131 auto time_t now; 132 register EVENT *ev; 133 134 signal(SIGALRM, SIG_IGN); 135 (void) time(&now); 136 137 # ifdef DEBUG 138 if (tTd(5, 1)) 139 printf("tick: now=%ld\n", now); 140 # endif DEBUG 141 142 while (EventQueue != NULL && EventQueue->ev_time <= now) 143 { 144 /* process the event on the top of the queue */ 145 ev = EventQueue; 146 EventQueue = EventQueue->ev_link; 147 # ifdef DEBUG 148 if (tTd(5, 3)) 149 printf("tick: ev=%x, func=%x, arg=%d\n", ev, 150 ev->ev_func, ev->ev_arg); 151 # endif DEBUG 152 (*ev->ev_func)(ev->ev_arg); 153 free(ev); 154 (void) time(&now); 155 } 156 157 /* schedule the next clock tick */ 158 signal(SIGALRM, tick); 159 if (EventQueue != NULL) 160 (void) alarm(EventQueue->ev_time - now); 161 } 162 /* 163 ** SLEEP -- a version of sleep that works with this stuff 164 ** 165 ** Because sleep uses the alarm facility, I must reimplement 166 ** it here. 167 ** 168 ** Parameters: 169 ** intvl -- time to sleep. 170 ** 171 ** Returns: 172 ** none. 173 ** 174 ** Side Effects: 175 ** waits for intvl time. However, other events can 176 ** be run during that interval. 177 */ 178 179 static bool SleepDone; 180 181 sleep(intvl) 182 int intvl; 183 { 184 extern endsleep(); 185 186 if (intvl == 0) 187 return; 188 SleepDone = FALSE; 189 setevent(intvl, endsleep, 0); 190 while (!SleepDone) 191 pause(); 192 } 193 194 static 195 endsleep() 196 { 197 SleepDone = TRUE; 198 } 199