17358Seric # include "sendmail.h" 27358Seric 3*7757Seric SCCSID(@(#)clock.c 3.5 08/15/82); 47358Seric 57358Seric /* 67684Seric ** SETEVENT -- set an event to happen at a specific time. 77684Seric ** 87684Seric ** Parameters: 97684Seric ** intvl -- intvl until next event occurs. 107684Seric ** func -- function to call on event. 117684Seric ** arg -- argument to func on event. 127684Seric ** 137684Seric ** Returns: 147684Seric ** none. 157684Seric ** 167684Seric ** Side Effects: 177684Seric ** none. 187684Seric */ 197684Seric 207684Seric EVENT * 217684Seric setevent(intvl, func, arg) 227684Seric time_t intvl; 237684Seric int (*func)(); 247684Seric int arg; 257684Seric { 267684Seric register EVENT **evp; 277684Seric register EVENT *ev; 287684Seric auto time_t now; 297684Seric extern tick(); 307684Seric 31*7757Seric # ifdef DEBUG 32*7757Seric if (intvl <= 0) 33*7757Seric { 34*7757Seric syserr("setevent: intvl=%ld\n", intvl); 35*7757Seric return; 36*7757Seric } 37*7757Seric # endif DEBUG 38*7757Seric 397684Seric (void) time(&now); 407684Seric 417684Seric /* search event queue for correct position */ 427684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 437684Seric { 447684Seric if (ev->ev_time >= now + intvl) 457684Seric break; 467684Seric } 477684Seric 487684Seric /* insert new event */ 497684Seric ev = (EVENT *) xalloc(sizeof *ev); 507684Seric ev->ev_time = now + intvl; 517684Seric ev->ev_func = func; 527684Seric ev->ev_arg = arg; 537684Seric ev->ev_link = *evp; 547684Seric *evp = ev; 557684Seric 567684Seric /* reschedule next clock tick if appropriate */ 577684Seric if (ev == EventQueue) 587684Seric { 597684Seric /* we have a new event */ 607684Seric (void) signal(SIGALRM, tick); 617684Seric (void) alarm(intvl); 627684Seric } 637684Seric 647684Seric # ifdef DEBUG 657684Seric if (tTd(5, 2)) 667684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 677684Seric intvl, now + intvl, func, arg, ev); 687684Seric # endif DEBUG 697684Seric 707684Seric return (ev); 717684Seric } 727684Seric /* 737684Seric ** CLREVENT -- remove an event from the event queue. 747684Seric ** 757684Seric ** Parameters: 767684Seric ** ev -- pointer to event to remove. 777684Seric ** 787684Seric ** Returns: 797684Seric ** none. 807684Seric ** 817684Seric ** Side Effects: 827684Seric ** arranges for event ev to not happen. 837684Seric */ 847684Seric 857684Seric clrevent(ev) 867684Seric register EVENT *ev; 877684Seric { 887684Seric register EVENT **evp; 897684Seric 907684Seric # ifdef DEBUG 917684Seric if (tTd(5, 2)) 927684Seric printf("clrevent: ev=%x\n", ev); 937684Seric # endif DEBUG 94*7757Seric if (ev == NULL) 95*7757Seric return; 967684Seric 977684Seric /* find the parent event */ 987684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 997684Seric { 1007684Seric if (*evp == ev) 1017684Seric break; 1027684Seric } 1037684Seric 1047684Seric /* now remove it */ 1057684Seric if (*evp == NULL) 1067684Seric { 1077684Seric /* hmmmmm.... must have happened. */ 1087684Seric return; 1097684Seric } 1107684Seric 1117684Seric *evp = ev->ev_link; 1127684Seric free(ev); 1137684Seric } 1147684Seric /* 1157358Seric ** TICK -- take a clock tick 1167358Seric ** 1177684Seric ** Called by the alarm clock. This routine runs events as needed. 1187358Seric ** 1197358Seric ** Parameters: 1207358Seric ** none. 1217358Seric ** 1227358Seric ** Returns: 1237684Seric ** none. 1247358Seric ** 1257358Seric ** Side Effects: 1267684Seric ** calls the next function in EventQueue. 1277358Seric */ 1287358Seric 1297358Seric tick() 1307358Seric { 1317684Seric auto time_t now; 1327684Seric register EVENT *ev; 1337684Seric 1347690Seric signal(SIGALRM, SIG_IGN); 1357684Seric (void) time(&now); 1367684Seric 1377358Seric # ifdef DEBUG 1387674Seric if (tTd(5, 1)) 1397684Seric printf("tick: now=%ld\n", now); 1407358Seric # endif DEBUG 1417684Seric 1427684Seric while (EventQueue != NULL && EventQueue->ev_time <= now) 1437684Seric { 1447684Seric /* process the event on the top of the queue */ 1457684Seric ev = EventQueue; 1467684Seric EventQueue = EventQueue->ev_link; 1477684Seric # ifdef DEBUG 1487684Seric if (tTd(5, 3)) 1497684Seric printf("tick: ev=%x, func=%x, arg=%d\n", ev, 1507684Seric ev->ev_func, ev->ev_arg); 1517684Seric # endif DEBUG 1527684Seric (*ev->ev_func)(ev->ev_arg); 1537684Seric free(ev); 1547684Seric (void) time(&now); 1557684Seric } 1567684Seric 1577684Seric /* schedule the next clock tick */ 1587684Seric signal(SIGALRM, tick); 1597684Seric if (EventQueue != NULL) 1607684Seric (void) alarm(EventQueue->ev_time - now); 1617358Seric } 1627690Seric /* 1637690Seric ** SLEEP -- a version of sleep that works with this stuff 1647690Seric ** 1657690Seric ** Because sleep uses the alarm facility, I must reimplement 1667690Seric ** it here. 1677690Seric ** 1687690Seric ** Parameters: 1697690Seric ** intvl -- time to sleep. 1707690Seric ** 1717690Seric ** Returns: 1727690Seric ** none. 1737690Seric ** 1747690Seric ** Side Effects: 1757690Seric ** waits for intvl time. However, other events can 1767690Seric ** be run during that interval. 1777690Seric */ 1787690Seric 1797690Seric static bool SleepDone; 1807690Seric 1817690Seric sleep(intvl) 1827690Seric int intvl; 1837690Seric { 1847690Seric extern endsleep(); 1857690Seric 186*7757Seric if (intvl == 0) 187*7757Seric return; 1887690Seric SleepDone = FALSE; 1897690Seric setevent(intvl, endsleep, 0); 1907690Seric while (!SleepDone) 1917690Seric pause(); 1927690Seric } 1937690Seric 1947690Seric static 1957690Seric endsleep() 1967690Seric { 1977690Seric SleepDone = TRUE; 1987690Seric } 199