17358Seric # include "sendmail.h" 27358Seric 3*7939Seric SCCSID(@(#)clock.c 3.9 08/27/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 587684Seric if (tTd(5, 2)) 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 63*7939Seric 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 857684Seric if (tTd(5, 2)) 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 */ 100*7939Seric if (*evp != NULL) 101*7939Seric { 102*7939Seric *evp = ev->ev_link; 103*7939Seric free(ev); 104*7939Seric } 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 1337674Seric if (tTd(5, 1)) 1347684Seric printf("tick: now=%ld\n", now); 1357358Seric # endif DEBUG 1367684Seric 1377684Seric while (EventQueue != NULL && EventQueue->ev_time <= now) 1387684Seric { 1397862Seric int (*f)(), a; 1407931Seric int pid; 1417862Seric 1427684Seric /* process the event on the top of the queue */ 1437684Seric ev = EventQueue; 1447684Seric EventQueue = EventQueue->ev_link; 1457684Seric # ifdef DEBUG 1467684Seric if (tTd(5, 3)) 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; 1547931Seric pid = ev->ev_pid; 1557684Seric free(ev); 1567931Seric if (pid != getpid()) 1577931Seric continue; 1587862Seric if (EventQueue != NULL) 1597862Seric { 1607862Seric if (EventQueue->ev_time > now) 1617862Seric (void) alarm(EventQueue->ev_time - now); 1627862Seric else 1637889Seric (void) alarm(3); 1647862Seric } 1657862Seric (*f)(a); 1667862Seric (void) alarm(0); 1677889Seric now = curtime(); 1687684Seric } 1697889Seric if (EventQueue != NULL) 1707889Seric (void) alarm(EventQueue->ev_time - now); 1717358Seric } 1727690Seric /* 1737690Seric ** SLEEP -- a version of sleep that works with this stuff 1747690Seric ** 1757690Seric ** Because sleep uses the alarm facility, I must reimplement 1767690Seric ** it here. 1777690Seric ** 1787690Seric ** Parameters: 1797690Seric ** intvl -- time to sleep. 1807690Seric ** 1817690Seric ** Returns: 1827690Seric ** none. 1837690Seric ** 1847690Seric ** Side Effects: 1857690Seric ** waits for intvl time. However, other events can 1867690Seric ** be run during that interval. 1877690Seric */ 1887690Seric 1897690Seric static bool SleepDone; 1907690Seric 1917690Seric sleep(intvl) 1927690Seric int intvl; 1937690Seric { 1947690Seric extern endsleep(); 1957690Seric 1967757Seric if (intvl == 0) 1977757Seric return; 1987690Seric SleepDone = FALSE; 1997690Seric setevent(intvl, endsleep, 0); 2007690Seric while (!SleepDone) 2017690Seric pause(); 2027690Seric } 2037690Seric 2047690Seric static 2057690Seric endsleep() 2067690Seric { 2077690Seric SleepDone = TRUE; 2087690Seric } 209