Simplify and avoid signal-handling races.
[bpt/emacs.git] / src / atimer.c
1 /* Asynchronous timers.
2 Copyright (C) 2000-2012 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include <config.h>
20 #include <stdio.h>
21
22 #include "lisp.h"
23 #include "syssignal.h"
24 #include "systime.h"
25 #include "blockinput.h"
26 #include "atimer.h"
27 #include <unistd.h>
28
29 /* Free-list of atimer structures. */
30
31 static struct atimer *free_atimers;
32
33 /* List of currently not running timers due to a call to
34 lock_atimer. */
35
36 static struct atimer *stopped_atimers;
37
38 /* List of active atimers, sorted by expiration time. The timer that
39 will become ripe next is always at the front of this list. */
40
41 static struct atimer *atimers;
42
43 /* Block/unblock SIGALRM. */
44
45 static void
46 sigmask_atimers (int how)
47 {
48 sigset_t blocked;
49 sigemptyset (&blocked);
50 sigaddset (&blocked, SIGALRM);
51 pthread_sigmask (how, &blocked, 0);
52 }
53 static void
54 block_atimers (void)
55 {
56 sigmask_atimers (SIG_BLOCK);
57 }
58 static void
59 unblock_atimers (void)
60 {
61 sigmask_atimers (SIG_UNBLOCK);
62 }
63
64 /* Function prototypes. */
65
66 static void set_alarm (void);
67 static void schedule_atimer (struct atimer *);
68 static struct atimer *append_atimer_lists (struct atimer *,
69 struct atimer *);
70
71 /* Start a new atimer of type TYPE. TIME specifies when the timer is
72 ripe. FN is the function to call when the timer fires.
73 CLIENT_DATA is stored in the client_data member of the atimer
74 structure returned and so made available to FN when it is called.
75
76 If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the
77 timer fires.
78
79 If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the
80 future.
81
82 In both cases, the timer is automatically freed after it has fired.
83
84 If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us.
85
86 Value is a pointer to the atimer started. It can be used in calls
87 to cancel_atimer; don't free it yourself. */
88
89 struct atimer *
90 start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
91 void *client_data)
92 {
93 struct atimer *t;
94
95 /* Round TIME up to the next full second if we don't have
96 itimers. */
97 #ifndef HAVE_SETITIMER
98 if (EMACS_NSECS (timestamp) != 0
99 && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t))
100 timestamp = make_emacs_time (EMACS_SECS (timestamp) + 1, 0);
101 #endif /* not HAVE_SETITIMER */
102
103 /* Get an atimer structure from the free-list, or allocate
104 a new one. */
105 if (free_atimers)
106 {
107 t = free_atimers;
108 free_atimers = t->next;
109 }
110 else
111 t = xmalloc (sizeof *t);
112
113 /* Fill the atimer structure. */
114 memset (t, 0, sizeof *t);
115 t->type = type;
116 t->fn = fn;
117 t->client_data = client_data;
118
119 block_atimers ();
120
121 /* Compute the timer's expiration time. */
122 switch (type)
123 {
124 case ATIMER_ABSOLUTE:
125 t->expiration = timestamp;
126 break;
127
128 case ATIMER_RELATIVE:
129 t->expiration = add_emacs_time (current_emacs_time (), timestamp);
130 break;
131
132 case ATIMER_CONTINUOUS:
133 t->expiration = add_emacs_time (current_emacs_time (), timestamp);
134 t->interval = timestamp;
135 break;
136 }
137
138 /* Insert the timer in the list of active atimers. */
139 schedule_atimer (t);
140 unblock_atimers ();
141
142 /* Arrange for a SIGALRM at the time the next atimer is ripe. */
143 set_alarm ();
144
145 return t;
146 }
147
148
149 /* Cancel and free atimer TIMER. */
150
151 void
152 cancel_atimer (struct atimer *timer)
153 {
154 int i;
155
156 block_atimers ();
157
158 for (i = 0; i < 2; ++i)
159 {
160 struct atimer *t, *prev;
161 struct atimer **list = i ? &stopped_atimers : &atimers;
162
163 /* See if TIMER is active or stopped. */
164 for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
165 ;
166
167 /* If it is, take it off its list, and put in on the free-list.
168 We don't bother to arrange for setting a different alarm time,
169 since a too early one doesn't hurt. */
170 if (t)
171 {
172 if (prev)
173 prev->next = t->next;
174 else
175 *list = t->next;
176
177 t->next = free_atimers;
178 free_atimers = t;
179 break;
180 }
181 }
182
183 unblock_atimers ();
184 }
185
186
187 /* Append two lists of atimers LIST_1 and LIST_2 and return the
188 result list. */
189
190 static struct atimer *
191 append_atimer_lists (struct atimer *list_1, struct atimer *list_2)
192 {
193 if (list_1 == NULL)
194 return list_2;
195 else if (list_2 == NULL)
196 return list_1;
197 else
198 {
199 struct atimer *p;
200
201 for (p = list_1; p->next; p = p->next)
202 ;
203 p->next = list_2;
204 return list_1;
205 }
206 }
207
208
209 /* Stop all timers except timer T. T null means stop all timers. */
210
211 void
212 stop_other_atimers (struct atimer *t)
213 {
214 block_atimers ();
215
216 if (t)
217 {
218 struct atimer *p, *prev;
219
220 /* See if T is active. */
221 for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next)
222 ;
223
224 if (p == t)
225 {
226 if (prev)
227 prev->next = t->next;
228 else
229 atimers = t->next;
230 t->next = NULL;
231 }
232 else
233 /* T is not active. Let's handle this like T == 0. */
234 t = NULL;
235 }
236
237 stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
238 atimers = t;
239 unblock_atimers ();
240 }
241
242
243 /* Run all timers again, if some have been stopped with a call to
244 stop_other_atimers. */
245
246 static void
247 run_all_atimers (void)
248 {
249 if (stopped_atimers)
250 {
251 struct atimer *t = atimers;
252 struct atimer *next;
253
254 block_atimers ();
255 atimers = stopped_atimers;
256 stopped_atimers = NULL;
257
258 while (t)
259 {
260 next = t->next;
261 schedule_atimer (t);
262 t = next;
263 }
264
265 unblock_atimers ();
266 }
267 }
268
269
270 /* A version of run_all_atimers suitable for a record_unwind_protect. */
271
272 Lisp_Object
273 unwind_stop_other_atimers (Lisp_Object dummy)
274 {
275 run_all_atimers ();
276 return Qnil;
277 }
278
279
280 /* Arrange for a SIGALRM to arrive when the next timer is ripe. */
281
282 static void
283 set_alarm (void)
284 {
285 if (atimers)
286 {
287 #ifdef HAVE_SETITIMER
288 struct itimerval it;
289 #endif
290
291 /* Determine s/us till the next timer is ripe. */
292 EMACS_TIME now = current_emacs_time ();
293
294 /* Don't set the interval to 0; this disables the timer. */
295 EMACS_TIME interval = (EMACS_TIME_LE (atimers->expiration, now)
296 ? make_emacs_time (0, 1000 * 1000)
297 : sub_emacs_time (atimers->expiration, now));
298
299 #ifdef HAVE_SETITIMER
300
301 memset (&it, 0, sizeof it);
302 it.it_value = make_timeval (interval);
303 setitimer (ITIMER_REAL, &it, 0);
304 #else /* not HAVE_SETITIMER */
305 alarm (max (EMACS_SECS (interval), 1));
306 #endif /* not HAVE_SETITIMER */
307 }
308 }
309
310
311 /* Insert timer T into the list of active atimers `atimers', keeping
312 the list sorted by expiration time. T must not be in this list
313 already. */
314
315 static void
316 schedule_atimer (struct atimer *t)
317 {
318 struct atimer *a = atimers, *prev = NULL;
319
320 /* Look for the first atimer that is ripe after T. */
321 while (a && EMACS_TIME_GT (t->expiration, a->expiration))
322 prev = a, a = a->next;
323
324 /* Insert T in front of the atimer found, if any. */
325 if (prev)
326 prev->next = t;
327 else
328 atimers = t;
329
330 t->next = a;
331 }
332
333 static void
334 run_timers (void)
335 {
336 EMACS_TIME now = current_emacs_time ();
337
338 while (atimers && EMACS_TIME_LE (atimers->expiration, now))
339 {
340 struct atimer *t = atimers;
341 atimers = atimers->next;
342 t->fn (t);
343
344 if (t->type == ATIMER_CONTINUOUS)
345 {
346 t->expiration = add_emacs_time (now, t->interval);
347 schedule_atimer (t);
348 }
349 else
350 {
351 t->next = free_atimers;
352 free_atimers = t;
353 }
354 }
355
356 set_alarm ();
357 }
358
359
360 /* Signal handler for SIGALRM. SIGNO is the signal number, i.e.
361 SIGALRM. */
362
363 static void
364 handle_alarm_signal (int sig)
365 {
366 pending_signals = 1;
367 }
368
369
370 /* Do pending timers. */
371
372 void
373 do_pending_atimers (void)
374 {
375 if (atimers)
376 {
377 block_atimers ();
378 run_timers ();
379 unblock_atimers ();
380 }
381 }
382
383
384 /* Turn alarms on/off. This seems to be temporarily necessary on
385 some systems like HPUX (see process.c). */
386
387 void
388 turn_on_atimers (bool on)
389 {
390 if (on)
391 set_alarm ();
392 else
393 alarm (0);
394 }
395
396
397 void
398 init_atimer (void)
399 {
400 struct sigaction action;
401 free_atimers = stopped_atimers = atimers = NULL;
402 /* pending_signals is initialized in init_keyboard.*/
403 emacs_sigaction_init (&action, handle_alarm_signal);
404 sigaction (SIGALRM, &action, 0);
405 }