|
|
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.