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