17358Seric # include "sendmail.h" 27358Seric 3*7889Seric SCCSID(@(#)clock.c 3.7 08/25/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 317757Seric # ifdef DEBUG 327757Seric if (intvl <= 0) 337757Seric { 347757Seric syserr("setevent: intvl=%ld\n", intvl); 357757Seric return; 367757Seric } 377757Seric # endif DEBUG 387757Seric 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 947757Seric if (ev == NULL) 957757Seric return; 967684Seric 977684Seric /* find the parent event */ 987862Seric signal(SIGALRM, SIG_IGN); 997684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1007684Seric { 1017684Seric if (*evp == ev) 1027684Seric break; 1037684Seric } 1047684Seric 1057684Seric /* now remove it */ 1067684Seric *evp = ev->ev_link; 1077684Seric free(ev); 1087862Seric 1097862Seric /* restore clocks and pick up anything spare */ 1107862Seric tick(); 1117684Seric } 1127684Seric /* 1137358Seric ** TICK -- take a clock tick 1147358Seric ** 1157684Seric ** Called by the alarm clock. This routine runs events as needed. 1167358Seric ** 1177358Seric ** Parameters: 1187358Seric ** none. 1197358Seric ** 1207358Seric ** Returns: 1217684Seric ** none. 1227358Seric ** 1237358Seric ** Side Effects: 1247684Seric ** calls the next function in EventQueue. 1257358Seric */ 1267358Seric 1277358Seric tick() 1287358Seric { 129*7889Seric register time_t now; 1307684Seric register EVENT *ev; 1317684Seric 1327862Seric signal(SIGALRM, tick); 133*7889Seric now = curtime(); 1347684Seric 1357358Seric # ifdef DEBUG 1367674Seric if (tTd(5, 1)) 1377684Seric printf("tick: now=%ld\n", now); 1387358Seric # endif DEBUG 1397684Seric 1407684Seric while (EventQueue != NULL && EventQueue->ev_time <= now) 1417684Seric { 1427862Seric int (*f)(), a; 1437862Seric 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 1527862Seric 1537862Seric /* we must be careful in here because ev_func may not return */ 1547862Seric f = ev->ev_func; 1557862Seric a = ev->ev_arg; 1567684Seric free(ev); 1577862Seric if (EventQueue != NULL) 1587862Seric { 1597862Seric if (EventQueue->ev_time > now) 1607862Seric (void) alarm(EventQueue->ev_time - now); 1617862Seric else 162*7889Seric (void) alarm(3); 1637862Seric } 1647862Seric (*f)(a); 1657862Seric (void) alarm(0); 166*7889Seric now = curtime(); 1677684Seric } 168*7889Seric if (EventQueue != NULL) 169*7889Seric (void) alarm(EventQueue->ev_time - now); 1707358Seric } 1717690Seric /* 1727690Seric ** SLEEP -- a version of sleep that works with this stuff 1737690Seric ** 1747690Seric ** Because sleep uses the alarm facility, I must reimplement 1757690Seric ** it here. 1767690Seric ** 1777690Seric ** Parameters: 1787690Seric ** intvl -- time to sleep. 1797690Seric ** 1807690Seric ** Returns: 1817690Seric ** none. 1827690Seric ** 1837690Seric ** Side Effects: 1847690Seric ** waits for intvl time. However, other events can 1857690Seric ** be run during that interval. 1867690Seric */ 1877690Seric 1887690Seric static bool SleepDone; 1897690Seric 1907690Seric sleep(intvl) 1917690Seric int intvl; 1927690Seric { 1937690Seric extern endsleep(); 1947690Seric 1957757Seric if (intvl == 0) 1967757Seric return; 1977690Seric SleepDone = FALSE; 1987690Seric setevent(intvl, endsleep, 0); 1997690Seric while (!SleepDone) 2007690Seric pause(); 2017690Seric } 2027690Seric 2037690Seric static 2047690Seric endsleep() 2057690Seric { 2067690Seric SleepDone = TRUE; 2077690Seric } 208