1 # include "sendmail.h" 2 3 SCCSID(@(#)clock.c 3.8 08/27/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_pid = getpid(); 54 ev->ev_link = *evp; 55 *evp = ev; 56 57 /* reschedule next clock tick if appropriate */ 58 if (ev == EventQueue) 59 { 60 /* we have a new event */ 61 (void) signal(SIGALRM, tick); 62 (void) alarm(intvl); 63 } 64 65 # ifdef DEBUG 66 if (tTd(5, 2)) 67 printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 68 intvl, now + intvl, func, arg, ev); 69 # endif DEBUG 70 71 return (ev); 72 } 73 /* 74 ** CLREVENT -- remove an event from the event queue. 75 ** 76 ** Parameters: 77 ** ev -- pointer to event to remove. 78 ** 79 ** Returns: 80 ** none. 81 ** 82 ** Side Effects: 83 ** arranges for event ev to not happen. 84 */ 85 86 clrevent(ev) 87 register EVENT *ev; 88 { 89 register EVENT **evp; 90 91 # ifdef DEBUG 92 if (tTd(5, 2)) 93 printf("clrevent: ev=%x\n", ev); 94 # endif DEBUG 95 if (ev == NULL) 96 return; 97 98 /* find the parent event */ 99 signal(SIGALRM, SIG_IGN); 100 for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 101 { 102 if (*evp == ev) 103 break; 104 } 105 106 /* now remove it */ 107 *evp = ev->ev_link; 108 free(ev); 109 110 /* restore clocks and pick up anything spare */ 111 tick(); 112 } 113 /* 114 ** TICK -- take a clock tick 115 ** 116 ** Called by the alarm clock. This routine runs events as needed. 117 ** 118 ** Parameters: 119 ** none. 120 ** 121 ** Returns: 122 ** none. 123 ** 124 ** Side Effects: 125 ** calls the next function in EventQueue. 126 */ 127 128 tick() 129 { 130 register time_t now; 131 register EVENT *ev; 132 133 signal(SIGALRM, tick); 134 now = curtime(); 135 136 # ifdef DEBUG 137 if (tTd(5, 1)) 138 printf("tick: now=%ld\n", now); 139 # endif DEBUG 140 141 while (EventQueue != NULL && EventQueue->ev_time <= now) 142 { 143 int (*f)(), a; 144 int pid; 145 146 /* process the event on the top of the queue */ 147 ev = EventQueue; 148 EventQueue = EventQueue->ev_link; 149 # ifdef DEBUG 150 if (tTd(5, 3)) 151 printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 152 ev->ev_func, ev->ev_arg, ev->ev_pid); 153 # endif DEBUG 154 155 /* we must be careful in here because ev_func may not return */ 156 f = ev->ev_func; 157 a = ev->ev_arg; 158 pid = ev->ev_pid; 159 free(ev); 160 if (pid != getpid()) 161 continue; 162 if (EventQueue != NULL) 163 { 164 if (EventQueue->ev_time > now) 165 (void) alarm(EventQueue->ev_time - now); 166 else 167 (void) alarm(3); 168 } 169 (*f)(a); 170 (void) alarm(0); 171 now = curtime(); 172 } 173 if (EventQueue != NULL) 174 (void) alarm(EventQueue->ev_time - now); 175 } 176 /* 177 ** SLEEP -- a version of sleep that works with this stuff 178 ** 179 ** Because sleep uses the alarm facility, I must reimplement 180 ** it here. 181 ** 182 ** Parameters: 183 ** intvl -- time to sleep. 184 ** 185 ** Returns: 186 ** none. 187 ** 188 ** Side Effects: 189 ** waits for intvl time. However, other events can 190 ** be run during that interval. 191 */ 192 193 static bool SleepDone; 194 195 sleep(intvl) 196 int intvl; 197 { 198 extern endsleep(); 199 200 if (intvl == 0) 201 return; 202 SleepDone = FALSE; 203 setevent(intvl, endsleep, 0); 204 while (!SleepDone) 205 pause(); 206 } 207 208 static 209 endsleep() 210 { 211 SleepDone = TRUE; 212 } 213