17358Seric # include "sendmail.h" 211728Seric # include <signal.h> 37358Seric 4*17472Seric SCCSID(@(#)clock.c 4.3 12/05/84); 57358Seric 67358Seric /* 77684Seric ** SETEVENT -- set an event to happen at a specific time. 87684Seric ** 99373Seric ** Events are stored in a sorted list for fast processing. 109373Seric ** An event only applies to the process that set it. 119373Seric ** 127684Seric ** Parameters: 137684Seric ** intvl -- intvl until next event occurs. 147684Seric ** func -- function to call on event. 157684Seric ** arg -- argument to func on event. 167684Seric ** 177684Seric ** Returns: 187684Seric ** none. 197684Seric ** 207684Seric ** Side Effects: 217684Seric ** none. 227684Seric */ 237684Seric 247684Seric EVENT * 257684Seric setevent(intvl, func, arg) 267684Seric time_t intvl; 277684Seric int (*func)(); 287684Seric int arg; 297684Seric { 307684Seric register EVENT **evp; 317684Seric register EVENT *ev; 327684Seric auto time_t now; 337684Seric extern tick(); 347684Seric 357757Seric # ifdef DEBUG 367757Seric if (intvl <= 0) 377757Seric { 387757Seric syserr("setevent: intvl=%ld\n", intvl); 399346Seric return (NULL); 407757Seric } 417757Seric # endif DEBUG 427757Seric 437684Seric (void) time(&now); 447684Seric 457684Seric /* search event queue for correct position */ 467684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 477684Seric { 487684Seric if (ev->ev_time >= now + intvl) 497684Seric break; 507684Seric } 517684Seric 527684Seric /* insert new event */ 537684Seric ev = (EVENT *) xalloc(sizeof *ev); 547684Seric ev->ev_time = now + intvl; 557684Seric ev->ev_func = func; 567684Seric ev->ev_arg = arg; 577931Seric ev->ev_pid = getpid(); 587684Seric ev->ev_link = *evp; 597684Seric *evp = ev; 607684Seric 617684Seric # ifdef DEBUG 628063Seric if (tTd(5, 5)) 637684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 647684Seric intvl, now + intvl, func, arg, ev); 657684Seric # endif DEBUG 667684Seric 677939Seric tick(); 687684Seric return (ev); 697684Seric } 707684Seric /* 717684Seric ** CLREVENT -- remove an event from the event queue. 727684Seric ** 737684Seric ** Parameters: 747684Seric ** ev -- pointer to event to remove. 757684Seric ** 767684Seric ** Returns: 777684Seric ** none. 787684Seric ** 797684Seric ** Side Effects: 807684Seric ** arranges for event ev to not happen. 817684Seric */ 827684Seric 837684Seric clrevent(ev) 847684Seric register EVENT *ev; 857684Seric { 867684Seric register EVENT **evp; 877684Seric 887684Seric # ifdef DEBUG 898063Seric if (tTd(5, 5)) 907684Seric printf("clrevent: ev=%x\n", ev); 917684Seric # endif DEBUG 927757Seric if (ev == NULL) 937757Seric return; 947684Seric 957684Seric /* find the parent event */ 969373Seric (void) signal(SIGALRM, SIG_IGN); 977684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 987684Seric { 997684Seric if (*evp == ev) 1007684Seric break; 1017684Seric } 1027684Seric 1037684Seric /* now remove it */ 1047939Seric if (*evp != NULL) 1057939Seric { 1067939Seric *evp = ev->ev_link; 1079346Seric free((char *) ev); 1087939Seric } 1097862Seric 1107862Seric /* restore clocks and pick up anything spare */ 1117862Seric tick(); 1127684Seric } 1137684Seric /* 1147358Seric ** TICK -- take a clock tick 1157358Seric ** 1167684Seric ** Called by the alarm clock. This routine runs events as needed. 1177358Seric ** 1187358Seric ** Parameters: 1197358Seric ** none. 1207358Seric ** 1217358Seric ** Returns: 1227684Seric ** none. 1237358Seric ** 1247358Seric ** Side Effects: 1257684Seric ** calls the next function in EventQueue. 1267358Seric */ 1277358Seric 1287358Seric tick() 1297358Seric { 1307889Seric register time_t now; 1317684Seric register EVENT *ev; 132*17472Seric int pid = getpid(); 1337684Seric 1349373Seric (void) signal(SIGALRM, SIG_IGN); 1359373Seric (void) alarm(0); 1367889Seric now = curtime(); 1377684Seric 1387358Seric # ifdef DEBUG 1398063Seric if (tTd(5, 4)) 1407684Seric printf("tick: now=%ld\n", now); 1417358Seric # endif DEBUG 1427684Seric 1438128Seric while ((ev = EventQueue) != NULL && 144*17472Seric (ev->ev_time <= now || ev->ev_pid != pid)) 1457684Seric { 14616141Seric int (*f)(); 14716141Seric int arg; 14816141Seric int pid; 1497862Seric 1507684Seric /* process the event on the top of the queue */ 1517684Seric ev = EventQueue; 1527684Seric EventQueue = EventQueue->ev_link; 1537684Seric # ifdef DEBUG 1548063Seric if (tTd(5, 6)) 1557931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1567931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1577684Seric # endif DEBUG 1587862Seric 1597862Seric /* we must be careful in here because ev_func may not return */ 1609373Seric (void) signal(SIGALRM, tick); 1617862Seric f = ev->ev_func; 16216141Seric arg = ev->ev_arg; 16316141Seric pid = ev->ev_pid; 1649346Seric free((char *) ev); 16516141Seric if (pid != getpid()) 1667931Seric continue; 1677862Seric if (EventQueue != NULL) 1687862Seric { 1697862Seric if (EventQueue->ev_time > now) 17012635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1717862Seric else 1727889Seric (void) alarm(3); 1737862Seric } 17416141Seric (*f)(arg); 1757862Seric (void) alarm(0); 1767889Seric now = curtime(); 1777684Seric } 1789373Seric (void) signal(SIGALRM, tick); 1797889Seric if (EventQueue != NULL) 18012635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1817358Seric } 1827690Seric /* 1837690Seric ** SLEEP -- a version of sleep that works with this stuff 1847690Seric ** 1857690Seric ** Because sleep uses the alarm facility, I must reimplement 1867690Seric ** it here. 1877690Seric ** 1887690Seric ** Parameters: 1897690Seric ** intvl -- time to sleep. 1907690Seric ** 1917690Seric ** Returns: 1927690Seric ** none. 1937690Seric ** 1947690Seric ** Side Effects: 1957690Seric ** waits for intvl time. However, other events can 1967690Seric ** be run during that interval. 1977690Seric */ 1987690Seric 1997690Seric static bool SleepDone; 2007690Seric 2017690Seric sleep(intvl) 2027690Seric int intvl; 2037690Seric { 2047690Seric extern endsleep(); 2057690Seric 2067757Seric if (intvl == 0) 2077757Seric return; 2087690Seric SleepDone = FALSE; 20912635Seric (void) setevent((time_t) intvl, endsleep, 0); 2107690Seric while (!SleepDone) 2117690Seric pause(); 2127690Seric } 2137690Seric 2147690Seric static 2157690Seric endsleep() 2167690Seric { 2177690Seric SleepDone = TRUE; 2187690Seric } 219