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