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