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