17358Seric # include "sendmail.h" 27358Seric 3*8128Seric SCCSID(@(#)clock.c 3.11 09/08/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; 537931Seric ev->ev_pid = getpid(); 547684Seric ev->ev_link = *evp; 557684Seric *evp = ev; 567684Seric 577684Seric # ifdef DEBUG 588063Seric if (tTd(5, 5)) 597684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 607684Seric intvl, now + intvl, func, arg, ev); 617684Seric # endif DEBUG 627684Seric 637939Seric tick(); 647684Seric return (ev); 657684Seric } 667684Seric /* 677684Seric ** CLREVENT -- remove an event from the event queue. 687684Seric ** 697684Seric ** Parameters: 707684Seric ** ev -- pointer to event to remove. 717684Seric ** 727684Seric ** Returns: 737684Seric ** none. 747684Seric ** 757684Seric ** Side Effects: 767684Seric ** arranges for event ev to not happen. 777684Seric */ 787684Seric 797684Seric clrevent(ev) 807684Seric register EVENT *ev; 817684Seric { 827684Seric register EVENT **evp; 837684Seric 847684Seric # ifdef DEBUG 858063Seric if (tTd(5, 5)) 867684Seric printf("clrevent: ev=%x\n", ev); 877684Seric # endif DEBUG 887757Seric if (ev == NULL) 897757Seric return; 907684Seric 917684Seric /* find the parent event */ 927862Seric signal(SIGALRM, SIG_IGN); 937684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 947684Seric { 957684Seric if (*evp == ev) 967684Seric break; 977684Seric } 987684Seric 997684Seric /* now remove it */ 1007939Seric if (*evp != NULL) 1017939Seric { 1027939Seric *evp = ev->ev_link; 1037939Seric free(ev); 1047939Seric } 1057862Seric 1067862Seric /* restore clocks and pick up anything spare */ 1077862Seric tick(); 1087684Seric } 1097684Seric /* 1107358Seric ** TICK -- take a clock tick 1117358Seric ** 1127684Seric ** Called by the alarm clock. This routine runs events as needed. 1137358Seric ** 1147358Seric ** Parameters: 1157358Seric ** none. 1167358Seric ** 1177358Seric ** Returns: 1187684Seric ** none. 1197358Seric ** 1207358Seric ** Side Effects: 1217684Seric ** calls the next function in EventQueue. 1227358Seric */ 1237358Seric 1247358Seric tick() 1257358Seric { 1267889Seric register time_t now; 1277684Seric register EVENT *ev; 1287684Seric 1297862Seric signal(SIGALRM, tick); 1307889Seric now = curtime(); 1317684Seric 1327358Seric # ifdef DEBUG 1338063Seric if (tTd(5, 4)) 1347684Seric printf("tick: now=%ld\n", now); 1357358Seric # endif DEBUG 1367684Seric 137*8128Seric while ((ev = EventQueue) != NULL && 138*8128Seric (ev->ev_time <= now || ev->ev_pid != getpid())) 1397684Seric { 1407862Seric int (*f)(), a; 1417862Seric 1427684Seric /* process the event on the top of the queue */ 1437684Seric ev = EventQueue; 1447684Seric EventQueue = EventQueue->ev_link; 1457684Seric # ifdef DEBUG 1468063Seric if (tTd(5, 6)) 1477931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1487931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1497684Seric # endif DEBUG 1507862Seric 1517862Seric /* we must be careful in here because ev_func may not return */ 1527862Seric f = ev->ev_func; 1537862Seric a = ev->ev_arg; 1547684Seric free(ev); 155*8128Seric if (ev->ev_pid != getpid()) 1567931Seric continue; 1577862Seric if (EventQueue != NULL) 1587862Seric { 1597862Seric if (EventQueue->ev_time > now) 1607862Seric (void) alarm(EventQueue->ev_time - now); 1617862Seric else 1627889Seric (void) alarm(3); 1637862Seric } 1647862Seric (*f)(a); 1657862Seric (void) alarm(0); 1667889Seric now = curtime(); 1677684Seric } 1687889Seric if (EventQueue != NULL) 1697889Seric (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