1 # include "sendmail.h" 2 3 SCCSID(@(#)clock.c 3.7 08/25/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 signal(SIGALRM, SIG_IGN); 99 for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 100 { 101 if (*evp == ev) 102 break; 103 } 104 105 /* now remove it */ 106 *evp = ev->ev_link; 107 free(ev); 108 109 /* restore clocks and pick up anything spare */ 110 tick(); 111 } 112 /* 113 ** TICK -- take a clock tick 114 ** 115 ** Called by the alarm clock. This routine runs events as needed. 116 ** 117 ** Parameters: 118 ** none. 119 ** 120 ** Returns: 121 ** none. 122 ** 123 ** Side Effects: 124 ** calls the next function in EventQueue. 125 */ 126 127 tick() 128 { 129 register time_t now; 130 register EVENT *ev; 131 132 signal(SIGALRM, tick); 133 now = curtime(); 134 135 # ifdef DEBUG 136 if (tTd(5, 1)) 137 printf("tick: now=%ld\n", now); 138 # endif DEBUG 139 140 while (EventQueue != NULL && EventQueue->ev_time <= now) 141 { 142 int (*f)(), a; 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 153 /* we must be careful in here because ev_func may not return */ 154 f = ev->ev_func; 155 a = ev->ev_arg; 156 free(ev); 157 if (EventQueue != NULL) 158 { 159 if (EventQueue->ev_time > now) 160 (void) alarm(EventQueue->ev_time - now); 161 else 162 (void) alarm(3); 163 } 164 (*f)(a); 165 (void) alarm(0); 166 now = curtime(); 167 } 168 if (EventQueue != NULL) 169 (void) alarm(EventQueue->ev_time - now); 170 } 171 /* 172 ** SLEEP -- a version of sleep that works with this stuff 173 ** 174 ** Because sleep uses the alarm facility, I must reimplement 175 ** it here. 176 ** 177 ** Parameters: 178 ** intvl -- time to sleep. 179 ** 180 ** Returns: 181 ** none. 182 ** 183 ** Side Effects: 184 ** waits for intvl time. However, other events can 185 ** be run during that interval. 186 */ 187 188 static bool SleepDone; 189 190 sleep(intvl) 191 int intvl; 192 { 193 extern endsleep(); 194 195 if (intvl == 0) 196 return; 197 SleepDone = FALSE; 198 setevent(intvl, endsleep, 0); 199 while (!SleepDone) 200 pause(); 201 } 202 203 static 204 endsleep() 205 { 206 SleepDone = TRUE; 207 } 208