|
|
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 provided ! 7: * that: (1) source distributions retain this entire copyright notice and ! 8: * comment, and (2) distributions including binaries display the following ! 9: * acknowledgement: ``This product includes software developed by the ! 10: * University of California, Berkeley and its contributors'' in the ! 11: * documentation or other materials provided with the distribution and in ! 12: * all advertising materials mentioning features or use of this software. ! 13: * Neither the name of the University nor the names of its contributors may ! 14: * be used to endorse or promote products derived from this software without ! 15: * specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: */ ! 20: ! 21: #ifndef lint ! 22: static char sccsid[] = "@(#)clock.c 5.8 (Berkeley) 6/1/90"; ! 23: #endif /* not lint */ ! 24: ! 25: # include "sendmail.h" ! 26: # include <signal.h> ! 27: ! 28: /* ! 29: ** SETEVENT -- set an event to happen at a specific time. ! 30: ** ! 31: ** Events are stored in a sorted list for fast processing. ! 32: ** An event only applies to the process that set it. ! 33: ** ! 34: ** Parameters: ! 35: ** intvl -- intvl until next event occurs. ! 36: ** func -- function to call on event. ! 37: ** arg -- argument to func on event. ! 38: ** ! 39: ** Returns: ! 40: ** none. ! 41: ** ! 42: ** Side Effects: ! 43: ** none. ! 44: */ ! 45: ! 46: EVENT * ! 47: setevent(intvl, func, arg) ! 48: time_t intvl; ! 49: int (*func)(); ! 50: int arg; ! 51: { ! 52: register EVENT **evp; ! 53: register EVENT *ev; ! 54: auto time_t now; ! 55: extern tick(); ! 56: ! 57: if (intvl <= 0) ! 58: { ! 59: syserr("setevent: intvl=%ld\n", intvl); ! 60: return (NULL); ! 61: } ! 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: if (tTd(5, 5)) ! 82: printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n", ! 83: intvl, now + intvl, func, arg, ev); ! 84: ! 85: tick(); ! 86: return (ev); ! 87: } ! 88: /* ! 89: ** CLREVENT -- remove an event from the event queue. ! 90: ** ! 91: ** Parameters: ! 92: ** ev -- pointer to event to remove. ! 93: ** ! 94: ** Returns: ! 95: ** none. ! 96: ** ! 97: ** Side Effects: ! 98: ** arranges for event ev to not happen. ! 99: */ ! 100: ! 101: clrevent(ev) ! 102: register EVENT *ev; ! 103: { ! 104: register EVENT **evp; ! 105: ! 106: if (tTd(5, 5)) ! 107: printf("clrevent: ev=%x\n", ev); ! 108: if (ev == NULL) ! 109: return; ! 110: ! 111: /* find the parent event */ ! 112: (void) signal(SIGALRM, SIG_IGN); ! 113: for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) ! 114: { ! 115: if (*evp == ev) ! 116: break; ! 117: } ! 118: ! 119: /* now remove it */ ! 120: if (*evp != NULL) ! 121: { ! 122: *evp = ev->ev_link; ! 123: free((char *) ev); ! 124: } ! 125: ! 126: /* restore clocks and pick up anything spare */ ! 127: tick(); ! 128: } ! 129: /* ! 130: ** TICK -- take a clock tick ! 131: ** ! 132: ** Called by the alarm clock. This routine runs events as needed. ! 133: ** ! 134: ** Parameters: ! 135: ** none. ! 136: ** ! 137: ** Returns: ! 138: ** none. ! 139: ** ! 140: ** Side Effects: ! 141: ** calls the next function in EventQueue. ! 142: */ ! 143: ! 144: tick() ! 145: { ! 146: register time_t now; ! 147: register EVENT *ev; ! 148: int mypid = getpid(); ! 149: ! 150: (void) signal(SIGALRM, SIG_IGN); ! 151: (void) alarm(0); ! 152: now = curtime(); ! 153: ! 154: if (tTd(5, 4)) ! 155: printf("tick: now=%ld\n", now); ! 156: ! 157: while ((ev = EventQueue) != NULL && ! 158: (ev->ev_time <= now || ev->ev_pid != mypid)) ! 159: { ! 160: int (*f)(); ! 161: int arg; ! 162: int pid; ! 163: ! 164: /* process the event on the top of the queue */ ! 165: ev = EventQueue; ! 166: EventQueue = EventQueue->ev_link; ! 167: if (tTd(5, 6)) ! 168: printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev, ! 169: ev->ev_func, ev->ev_arg, ev->ev_pid); ! 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.