122696Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 6*42824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822696Sdist 922696Sdist #ifndef lint 10*42824Sbostic static char sccsid[] = "@(#)clock.c 5.8 (Berkeley) 06/01/90"; 1133728Sbostic #endif /* not lint */ 1222696Sdist 137358Seric # include "sendmail.h" 1411728Seric # include <signal.h> 157358Seric 167358Seric /* 177684Seric ** SETEVENT -- set an event to happen at a specific time. 187684Seric ** 199373Seric ** Events are stored in a sorted list for fast processing. 209373Seric ** An event only applies to the process that set it. 219373Seric ** 227684Seric ** Parameters: 237684Seric ** intvl -- intvl until next event occurs. 247684Seric ** func -- function to call on event. 257684Seric ** arg -- argument to func on event. 267684Seric ** 277684Seric ** Returns: 287684Seric ** none. 297684Seric ** 307684Seric ** Side Effects: 317684Seric ** none. 327684Seric */ 337684Seric 347684Seric EVENT * 357684Seric setevent(intvl, func, arg) 367684Seric time_t intvl; 377684Seric int (*func)(); 387684Seric int arg; 397684Seric { 407684Seric register EVENT **evp; 417684Seric register EVENT *ev; 427684Seric auto time_t now; 437684Seric extern tick(); 447684Seric 457757Seric if (intvl <= 0) 467757Seric { 477757Seric syserr("setevent: intvl=%ld\n", intvl); 489346Seric return (NULL); 497757Seric } 507757Seric 517684Seric (void) time(&now); 527684Seric 537684Seric /* search event queue for correct position */ 547684Seric for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) 557684Seric { 567684Seric if (ev->ev_time >= now + intvl) 577684Seric break; 587684Seric } 597684Seric 607684Seric /* insert new event */ 617684Seric ev = (EVENT *) xalloc(sizeof *ev); 627684Seric ev->ev_time = now + intvl; 637684Seric ev->ev_func = func; 647684Seric ev->ev_arg = arg; 657931Seric ev->ev_pid = getpid(); 667684Seric ev->ev_link = *evp; 677684Seric *evp = ev; 687684Seric 698063Seric if (tTd(5, 5)) 707684Seric printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", 717684Seric intvl, now + intvl, func, arg, ev); 727684Seric 737939Seric tick(); 747684Seric return (ev); 757684Seric } 767684Seric /* 777684Seric ** CLREVENT -- remove an event from the event queue. 787684Seric ** 797684Seric ** Parameters: 807684Seric ** ev -- pointer to event to remove. 817684Seric ** 827684Seric ** Returns: 837684Seric ** none. 847684Seric ** 857684Seric ** Side Effects: 867684Seric ** arranges for event ev to not happen. 877684Seric */ 887684Seric 897684Seric clrevent(ev) 907684Seric register EVENT *ev; 917684Seric { 927684Seric register EVENT **evp; 937684Seric 948063Seric if (tTd(5, 5)) 957684Seric printf("clrevent: ev=%x\n", ev); 967757Seric if (ev == NULL) 977757Seric return; 987684Seric 997684Seric /* find the parent event */ 1009373Seric (void) signal(SIGALRM, SIG_IGN); 1017684Seric for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) 1027684Seric { 1037684Seric if (*evp == ev) 1047684Seric break; 1057684Seric } 1067684Seric 1077684Seric /* now remove it */ 1087939Seric if (*evp != NULL) 1097939Seric { 1107939Seric *evp = ev->ev_link; 1119346Seric free((char *) ev); 1127939Seric } 1137862Seric 1147862Seric /* restore clocks and pick up anything spare */ 1157862Seric tick(); 1167684Seric } 1177684Seric /* 1187358Seric ** TICK -- take a clock tick 1197358Seric ** 1207684Seric ** Called by the alarm clock. This routine runs events as needed. 1217358Seric ** 1227358Seric ** Parameters: 1237358Seric ** none. 1247358Seric ** 1257358Seric ** Returns: 1267684Seric ** none. 1277358Seric ** 1287358Seric ** Side Effects: 1297684Seric ** calls the next function in EventQueue. 1307358Seric */ 1317358Seric 1327358Seric tick() 1337358Seric { 1347889Seric register time_t now; 1357684Seric register EVENT *ev; 13624955Seric int mypid = getpid(); 1377684Seric 1389373Seric (void) signal(SIGALRM, SIG_IGN); 1399373Seric (void) alarm(0); 1407889Seric now = curtime(); 1417684Seric 1428063Seric if (tTd(5, 4)) 1437684Seric printf("tick: now=%ld\n", now); 1447684Seric 1458128Seric while ((ev = EventQueue) != NULL && 14624955Seric (ev->ev_time <= now || ev->ev_pid != mypid)) 1477684Seric { 14816141Seric int (*f)(); 14916141Seric int arg; 15016141Seric int pid; 1517862Seric 1527684Seric /* process the event on the top of the queue */ 1537684Seric ev = EventQueue; 1547684Seric EventQueue = EventQueue->ev_link; 1558063Seric if (tTd(5, 6)) 1567931Seric printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, 1577931Seric ev->ev_func, ev->ev_arg, ev->ev_pid); 1587862Seric 1597862Seric /* we must be careful in here because ev_func may not return */ 1609373Seric (void) signal(SIGALRM, tick); 16120844Seric #ifdef SIGVTALRM 16220844Seric /* reset 4.2bsd signal mask to allow future alarms */ 16320844Seric (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 16420844Seric #endif SIGVTALRM 16520844Seric 1667862Seric f = ev->ev_func; 16716141Seric arg = ev->ev_arg; 16816141Seric pid = ev->ev_pid; 1699346Seric free((char *) ev); 17016141Seric if (pid != getpid()) 1717931Seric continue; 1727862Seric if (EventQueue != NULL) 1737862Seric { 1747862Seric if (EventQueue->ev_time > now) 17512635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1767862Seric else 1777889Seric (void) alarm(3); 1787862Seric } 17916141Seric (*f)(arg); 1807862Seric (void) alarm(0); 1817889Seric now = curtime(); 1827684Seric } 1839373Seric (void) signal(SIGALRM, tick); 1847889Seric if (EventQueue != NULL) 18512635Seric (void) alarm((unsigned) (EventQueue->ev_time - now)); 1867358Seric } 1877690Seric /* 1887690Seric ** SLEEP -- a version of sleep that works with this stuff 1897690Seric ** 1907690Seric ** Because sleep uses the alarm facility, I must reimplement 1917690Seric ** it here. 1927690Seric ** 1937690Seric ** Parameters: 1947690Seric ** intvl -- time to sleep. 1957690Seric ** 1967690Seric ** Returns: 1977690Seric ** none. 1987690Seric ** 1997690Seric ** Side Effects: 2007690Seric ** waits for intvl time. However, other events can 2017690Seric ** be run during that interval. 2027690Seric */ 2037690Seric 2047690Seric static bool SleepDone; 2057690Seric 2067690Seric sleep(intvl) 20725615Seric unsigned int intvl; 2087690Seric { 2097690Seric extern endsleep(); 2107690Seric 2117757Seric if (intvl == 0) 2127757Seric return; 2137690Seric SleepDone = FALSE; 21412635Seric (void) setevent((time_t) intvl, endsleep, 0); 2157690Seric while (!SleepDone) 2167690Seric pause(); 2177690Seric } 2187690Seric 2197690Seric static 2207690Seric endsleep() 2217690Seric { 2227690Seric SleepDone = TRUE; 2237690Seric } 224