Followup to not using maybe_unify_char in processing buffers and strings.
[bpt/emacs.git] / src / atimer.c
... / ...
CommitLineData
1/* Asynchronous timers.
2 Copyright (C) 2000-2012 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along 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
31static struct atimer *free_atimers;
32
33/* List of currently not running timers due to a call to
34 lock_atimer. */
35
36static 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
41static struct atimer *atimers;
42
43/* Block/unblock SIGALRM. */
44
45static void
46sigmask_atimers (int how)
47{
48 sigset_t blocked;
49 sigemptyset (&blocked);
50 sigaddset (&blocked, SIGALRM);
51 pthread_sigmask (how, &blocked, 0);
52}
53static void
54block_atimers (void)
55{
56 sigmask_atimers (SIG_BLOCK);
57}
58static void
59unblock_atimers (void)
60{
61 sigmask_atimers (SIG_UNBLOCK);
62}
63
64/* Function prototypes. */
65
66static void set_alarm (void);
67static void schedule_atimer (struct atimer *);
68static 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
89struct atimer *
90start_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
151void
152cancel_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
190static struct atimer *
191append_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
211void
212stop_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
246static void
247run_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
272Lisp_Object
273unwind_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
282static void
283set_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
315static void
316schedule_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
333static void
334run_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
363static void
364handle_alarm_signal (int sig)
365{
366 pending_signals = 1;
367}
368
369
370/* Do pending timers. */
371
372void
373do_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
387void
388turn_on_atimers (bool on)
389{
390 if (on)
391 set_alarm ();
392 else
393 alarm (0);
394}
395
396
397void
398init_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}