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