1 # include "sendmail.h" 2 3 SCCSID(@(#)clock.c 3.11 09/08/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, 5)) 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, 5)) 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, 4)) 134 printf("tick: now=%ld\n", now); 135 # endif DEBUG 136 137 while ((ev = EventQueue) != NULL && 138 (ev->ev_time <= now || ev->ev_pid != getpid())) 139 { 140 int (*f)(), a; 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, 6)) 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 free(ev); 155 if (ev->ev_pid != getpid()) 156 continue; 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