17358Seric # include "sendmail.h" 27358Seric 3*9373Seric SCCSID(@(#)clock.c 3.13 11/28/82); 47358Seric 57358Seric /* 67684Seric ** SETEVENT -- set an event to happen at a specific time. 77684Seric ** 8*9373Seric ** Events are stored in a sorted list for fast processing. 9*9373Seric ** An event only applies to the process that set it. 10*9373Seric ** 117684Seric ** Parameters: 127684Seric ** intvl -- intvl until next event occurs. 137684Seric ** func -- function to call on event. 147684Seric ** arg -- argument to func on event. 157684Seric ** 167684Seric ** Returns: 177684Seric ** none. 187684Seric ** 197684Seric ** Side Effects: 207684Seric ** none. 217684Seric */ 227684Seric 237684Seric EVENT * 247684Seric setevent(intvl, func, arg) 257684Seric time_t intvl; 267684Seric int (*func)(); 277684Seric int arg; 287684Seric { 297684Seric register EVENT **evp; 307684Seric register EVENT *ev; 317684Seric auto time_t now; 327684Seric extern tick(); 337684Seric 347757Seric # ifdef DEBUG 357757Seric if (intvl <= 0) 367757Seric { 377757Seric syserr("setevent: intvl=%ld\n", intvl); 389346Seric return (NULL); 397757Seric } 407757Seric # endif DEBUG 417757Seric 427684Seric (void) time(&now); 437684Seric 447684Seric /* search event queue for correct position */ 457684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 467684Seric { 477684Seric if (ev->ev_time >= now + intvl) 487684Seric break; 497684Seric } 507684Seric 517684Seric /* insert new event */ 527684Seric ev = (EVENT *) xalloc(sizeof *ev); 537684Seric ev->ev_time = now + intvl; 547684Seric ev->ev_func = func; 557684Seric ev->ev_arg = arg; 567931Seric ev->ev_pid = getpid(); 577684Seric ev->ev_link = *evp; 587684Seric *evp = ev; 597684Seric 607684Seric # ifdef DEBUG 618063Seric if (tTd(5, 5)) 627684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 637684Seric intvl, now + intvl, func, arg, ev); 647684Seric # endif DEBUG 657684Seric 667939Seric tick(); 677684Seric return (ev); 687684Seric } 697684Seric /* 707684Seric ** CLREVENT -- remove an event from the event queue. 717684Seric ** 727684Seric ** Parameters: 737684Seric ** ev -- pointer to event to remove. 747684Seric ** 757684Seric ** Returns: 767684Seric ** none. 777684Seric ** 787684Seric ** Side Effects: 797684Seric ** arranges for event ev to not happen. 807684Seric */ 817684Seric 827684Seric clrevent(ev) 837684Seric register EVENT *ev; 847684Seric { 857684Seric register EVENT **evp; 867684Seric 877684Seric # ifdef DEBUG 888063Seric if (tTd(5, 5)) 897684Seric printf("clrevent: ev=%x\n", ev); 907684Seric # endif DEBUG 917757Seric if (ev == NULL) 927757Seric return; 937684Seric 947684Seric /* find the parent event */ 95*9373Seric (void) signal(SIGALRM, SIG_IGN); 967684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 977684Seric { 987684Seric if (*evp == ev) 997684Seric break; 1007684Seric } 1017684Seric 1027684Seric /* now remove it */ 1037939Seric if (*evp != NULL) 1047939Seric { 1057939Seric *evp = ev->ev_link; 1069346Seric free((char *) ev); 1077939Seric } 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 { 1297889Seric register time_t now; 1307684Seric register EVENT *ev; 1317684Seric 132*9373Seric (void) signal(SIGALRM, SIG_IGN); 133*9373Seric (void) alarm(0); 1347889Seric now = curtime(); 1357684Seric 1367358Seric # ifdef DEBUG 1378063Seric if (tTd(5, 4)) 1387684Seric printf("tick: now=%ld\n", now); 1397358Seric # endif DEBUG 1407684Seric 1418128Seric while ((ev = EventQueue) != NULL && 1428128Seric (ev->ev_time <= now || ev->ev_pid != getpid())) 1437684Seric { 1447862Seric int (*f)(), a; 1457862Seric 1467684Seric /* process the event on the top of the queue */ 1477684Seric ev = EventQueue; 1487684Seric EventQueue = EventQueue->ev_link; 1497684Seric # ifdef DEBUG 1508063Seric if (tTd(5, 6)) 1517931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1527931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1537684Seric # endif DEBUG 1547862Seric 1557862Seric /* we must be careful in here because ev_func may not return */ 156*9373Seric (void) signal(SIGALRM, tick); 1577862Seric f = ev->ev_func; 1587862Seric a = ev->ev_arg; 1599346Seric free((char *) ev); 1608128Seric if (ev->ev_pid != getpid()) 1617931Seric continue; 1627862Seric if (EventQueue != NULL) 1637862Seric { 1647862Seric if (EventQueue->ev_time > now) 1657862Seric (void) alarm(EventQueue->ev_time - now); 1667862Seric else 1677889Seric (void) alarm(3); 1687862Seric } 1697862Seric (*f)(a); 1707862Seric (void) alarm(0); 1717889Seric now = curtime(); 1727684Seric } 173*9373Seric (void) signal(SIGALRM, tick); 1747889Seric if (EventQueue != NULL) 1757889Seric (void) alarm(EventQueue->ev_time - now); 1767358Seric } 1777690Seric /* 1787690Seric ** SLEEP -- a version of sleep that works with this stuff 1797690Seric ** 1807690Seric ** Because sleep uses the alarm facility, I must reimplement 1817690Seric ** it here. 1827690Seric ** 1837690Seric ** Parameters: 1847690Seric ** intvl -- time to sleep. 1857690Seric ** 1867690Seric ** Returns: 1877690Seric ** none. 1887690Seric ** 1897690Seric ** Side Effects: 1907690Seric ** waits for intvl time. However, other events can 1917690Seric ** be run during that interval. 1927690Seric */ 1937690Seric 1947690Seric static bool SleepDone; 1957690Seric 1967690Seric sleep(intvl) 1977690Seric int intvl; 1987690Seric { 1997690Seric extern endsleep(); 2007690Seric 2017757Seric if (intvl == 0) 2027757Seric return; 2037690Seric SleepDone = FALSE; 2049346Seric (void) setevent(intvl, endsleep, 0); 2057690Seric while (!SleepDone) 2067690Seric pause(); 2077690Seric } 2087690Seric 2097690Seric static 2107690Seric endsleep() 2117690Seric { 2127690Seric SleepDone = TRUE; 2137690Seric } 214