|
|
1.1 ! root 1: /* ! 2: ** Sendmail ! 3: ** Copyright (c) 1983 Eric P. Allman ! 4: ** Berkeley, California ! 5: ** ! 6: ** Copyright (c) 1983 Regents of the University of California. ! 7: ** All rights reserved. The Berkeley software License Agreement ! 8: ** specifies the terms and conditions for redistribution. ! 9: */ ! 10: ! 11: #ifndef lint ! 12: static char SccsId[] = "@(#)clock.c 5.4 (Berkeley) 12/17/85"; ! 13: #endif not lint ! 14: ! 15: # include "sendmail.h" ! 16: # include <signal.h> ! 17: ! 18: /* ! 19: ** SETEVENT -- set an event to happen at a specific time. ! 20: ** ! 21: ** Events are stored in a sorted list for fast processing. ! 22: ** An event only applies to the process that set it. ! 23: ** ! 24: ** Parameters: ! 25: ** intvl -- intvl until next event occurs. ! 26: ** func -- function to call on event. ! 27: ** arg -- argument to func on event. ! 28: ** ! 29: ** Returns: ! 30: ** none. ! 31: ** ! 32: ** Side Effects: ! 33: ** none. ! 34: */ ! 35: ! 36: EVENT * ! 37: setevent(intvl, func, arg) ! 38: time_t intvl; ! 39: int (*func)(); ! 40: int arg; ! 41: { ! 42: register EVENT **evp; ! 43: register EVENT *ev; ! 44: auto time_t now; ! 45: extern tick(); ! 46: ! 47: # ifdef DEBUG ! 48: if (intvl <= 0) ! 49: { ! 50: syserr("setevent: intvl=%ld\n", intvl); ! 51: return (NULL); ! 52: } ! 53: # endif DEBUG ! 54: ! 55: (void) time(&now); ! 56: ! 57: /* search event queue for correct position */ ! 58: for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) ! 59: { ! 60: if (ev->ev_time >= now + intvl) ! 61: break; ! 62: } ! 63: ! 64: /* insert new event */ ! 65: ev = (EVENT *) xalloc(sizeof *ev); ! 66: ev->ev_time = now + intvl; ! 67: ev->ev_func = func; ! 68: ev->ev_arg = arg; ! 69: ev->ev_pid = getpid(); ! 70: ev->ev_link = *evp; ! 71: *evp = ev; ! 72: ! 73: # ifdef DEBUG ! 74: if (tTd(5, 5)) ! 75: printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", ! 76: intvl, now + intvl, func, arg, ev); ! 77: # endif DEBUG ! 78: ! 79: tick(); ! 80: return (ev); ! 81: } ! 82: /* ! 83: ** CLREVENT -- remove an event from the event queue. ! 84: ** ! 85: ** Parameters: ! 86: ** ev -- pointer to event to remove. ! 87: ** ! 88: ** Returns: ! 89: ** none. ! 90: ** ! 91: ** Side Effects: ! 92: ** arranges for event ev to not happen. ! 93: */ ! 94: ! 95: clrevent(ev) ! 96: register EVENT *ev; ! 97: { ! 98: register EVENT **evp; ! 99: ! 100: # ifdef DEBUG ! 101: if (tTd(5, 5)) ! 102: printf("clrevent: ev=%x\n", ev); ! 103: # endif DEBUG ! 104: if (ev == NULL) ! 105: return; ! 106: ! 107: /* find the parent event */ ! 108: (void) signal(SIGALRM, SIG_IGN); ! 109: for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) ! 110: { ! 111: if (*evp == ev) ! 112: break; ! 113: } ! 114: ! 115: /* now remove it */ ! 116: if (*evp != NULL) ! 117: { ! 118: *evp = ev->ev_link; ! 119: free((char *) ev); ! 120: } ! 121: ! 122: /* restore clocks and pick up anything spare */ ! 123: tick(); ! 124: } ! 125: /* ! 126: ** TICK -- take a clock tick ! 127: ** ! 128: ** Called by the alarm clock. This routine runs events as needed. ! 129: ** ! 130: ** Parameters: ! 131: ** none. ! 132: ** ! 133: ** Returns: ! 134: ** none. ! 135: ** ! 136: ** Side Effects: ! 137: ** calls the next function in EventQueue. ! 138: */ ! 139: ! 140: tick() ! 141: { ! 142: register time_t now; ! 143: register EVENT *ev; ! 144: int mypid = getpid(); ! 145: ! 146: (void) signal(SIGALRM, SIG_IGN); ! 147: (void) alarm(0); ! 148: now = curtime(); ! 149: ! 150: # ifdef DEBUG ! 151: if (tTd(5, 4)) ! 152: printf("tick: now=%ld\n", now); ! 153: # endif DEBUG ! 154: ! 155: while ((ev = EventQueue) != NULL && ! 156: (ev->ev_time <= now || ev->ev_pid != mypid)) ! 157: { ! 158: int (*f)(); ! 159: int arg; ! 160: int pid; ! 161: ! 162: /* process the event on the top of the queue */ ! 163: ev = EventQueue; ! 164: EventQueue = EventQueue->ev_link; ! 165: # ifdef DEBUG ! 166: if (tTd(5, 6)) ! 167: printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, ! 168: ev->ev_func, ev->ev_arg, ev->ev_pid); ! 169: # endif DEBUG ! 170: ! 171: /* we must be careful in here because ev_func may not return */ ! 172: (void) signal(SIGALRM, tick); ! 173: #ifdef SIGVTALRM ! 174: /* reset 4.2bsd signal mask to allow future alarms */ ! 175: (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); ! 176: #endif SIGVTALRM ! 177: ! 178: f = ev->ev_func; ! 179: arg = ev->ev_arg; ! 180: pid = ev->ev_pid; ! 181: free((char *) ev); ! 182: if (pid != getpid()) ! 183: continue; ! 184: if (EventQueue != NULL) ! 185: { ! 186: if (EventQueue->ev_time > now) ! 187: (void) alarm((unsigned) (EventQueue->ev_time - now)); ! 188: else ! 189: (void) alarm(3); ! 190: } ! 191: (*f)(arg); ! 192: (void) alarm(0); ! 193: now = curtime(); ! 194: } ! 195: (void) signal(SIGALRM, tick); ! 196: if (EventQueue != NULL) ! 197: (void) alarm((unsigned) (EventQueue->ev_time - now)); ! 198: } ! 199: /* ! 200: ** SLEEP -- a version of sleep that works with this stuff ! 201: ** ! 202: ** Because sleep uses the alarm facility, I must reimplement ! 203: ** it here. ! 204: ** ! 205: ** Parameters: ! 206: ** intvl -- time to sleep. ! 207: ** ! 208: ** Returns: ! 209: ** none. ! 210: ** ! 211: ** Side Effects: ! 212: ** waits for intvl time. However, other events can ! 213: ** be run during that interval. ! 214: */ ! 215: ! 216: static bool SleepDone; ! 217: ! 218: sleep(intvl) ! 219: unsigned int intvl; ! 220: { ! 221: extern endsleep(); ! 222: ! 223: if (intvl == 0) ! 224: return; ! 225: SleepDone = FALSE; ! 226: (void) setevent((time_t) intvl, endsleep, 0); ! 227: while (!SleepDone) ! 228: pause(); ! 229: } ! 230: ! 231: static ! 232: endsleep() ! 233: { ! 234: SleepDone = TRUE; ! 235: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.