Followup to not using maybe_unify_char in processing buffers and strings.
[bpt/emacs.git] / src / atimer.c
CommitLineData
e12489f9 1/* Asynchronous timers.
acaf905b 2 Copyright (C) 2000-2012 Free Software Foundation, Inc.
e12489f9
GM
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
e12489f9 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
e12489f9
GM
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
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
e12489f9
GM
18
19#include <config.h>
5890e9f7 20#include <stdio.h>
0328b6de 21
898b4c5c
DN
22#include "lisp.h"
23#include "syssignal.h"
24#include "systime.h"
25#include "blockinput.h"
26#include "atimer.h"
e12489f9 27#include <unistd.h>
e12489f9 28
e12489f9
GM
29/* Free-list of atimer structures. */
30
31static struct atimer *free_atimers;
32
9c2e3e8d
GM
33/* List of currently not running timers due to a call to
34 lock_atimer. */
35
36static struct atimer *stopped_atimers;
37
e12489f9
GM
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
5f351ff1 43/* Block/unblock SIGALRM. */
e12489f9 44
2fe28299
PE
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}
e12489f9
GM
63
64/* Function prototypes. */
65
f57e2426
J
66static void set_alarm (void);
67static void schedule_atimer (struct atimer *);
68static struct atimer *append_atimer_lists (struct atimer *,
69 struct atimer *);
e12489f9
GM
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 *
3e7d6594 90start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
e5447b22 91 void *client_data)
e12489f9
GM
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
d35af63c
PE
98 if (EMACS_NSECS (timestamp) != 0
99 && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t))
e9a9ae03 100 timestamp = make_emacs_time (EMACS_SECS (timestamp) + 1, 0);
e12489f9
GM
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
23f86fce 111 t = xmalloc (sizeof *t);
e12489f9
GM
112
113 /* Fill the atimer structure. */
72af86bd 114 memset (t, 0, sizeof *t);
e12489f9
GM
115 t->type = type;
116 t->fn = fn;
117 t->client_data = client_data;
118
2fe28299 119 block_atimers ();
e12489f9
GM
120
121 /* Compute the timer's expiration time. */
122 switch (type)
123 {
124 case ATIMER_ABSOLUTE:
3e7d6594 125 t->expiration = timestamp;
e12489f9 126 break;
177c0ea7 127
e12489f9 128 case ATIMER_RELATIVE:
e9a9ae03 129 t->expiration = add_emacs_time (current_emacs_time (), timestamp);
e12489f9 130 break;
177c0ea7 131
e12489f9 132 case ATIMER_CONTINUOUS:
e9a9ae03 133 t->expiration = add_emacs_time (current_emacs_time (), timestamp);
3e7d6594 134 t->interval = timestamp;
e12489f9
GM
135 break;
136 }
137
138 /* Insert the timer in the list of active atimers. */
139 schedule_atimer (t);
2fe28299 140 unblock_atimers ();
e12489f9
GM
141
142 /* Arrange for a SIGALRM at the time the next atimer is ripe. */
143 set_alarm ();
177c0ea7 144
e12489f9
GM
145 return t;
146}
147
148
149/* Cancel and free atimer TIMER. */
150
151void
971de7fb 152cancel_atimer (struct atimer *timer)
e12489f9 153{
50b1039f 154 int i;
177c0ea7 155
2fe28299 156 block_atimers ();
e12489f9 157
50b1039f 158 for (i = 0; i < 2; ++i)
94870977 159 {
50b1039f
GM
160 struct atimer *t, *prev;
161 struct atimer **list = i ? &stopped_atimers : &atimers;
177c0ea7 162
94870977 163 /* See if TIMER is active or stopped. */
4ab1d4be 164 for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
94870977
GM
165 ;
166
88dbda51
JB
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. */
94870977
GM
170 if (t)
171 {
172 if (prev)
173 prev->next = t->next;
174 else
175 *list = t->next;
177c0ea7 176
94870977
GM
177 t->next = free_atimers;
178 free_atimers = t;
4ab1d4be 179 break;
94870977 180 }
e12489f9
GM
181 }
182
2fe28299 183 unblock_atimers ();
e12489f9
GM
184}
185
186
3e7d6594 187/* Append two lists of atimers LIST_1 and LIST_2 and return the
50b1039f
GM
188 result list. */
189
190static struct atimer *
3e7d6594 191append_atimer_lists (struct atimer *list_1, struct atimer *list_2)
50b1039f 192{
3e7d6594
PE
193 if (list_1 == NULL)
194 return list_2;
195 else if (list_2 == NULL)
196 return list_1;
50b1039f
GM
197 else
198 {
199 struct atimer *p;
177c0ea7 200
3e7d6594 201 for (p = list_1; p->next; p = p->next)
50b1039f 202 ;
3e7d6594
PE
203 p->next = list_2;
204 return list_1;
50b1039f
GM
205 }
206}
207
208
209/* Stop all timers except timer T. T null means stop all timers. */
9c2e3e8d
GM
210
211void
971de7fb 212stop_other_atimers (struct atimer *t)
9c2e3e8d 213{
2fe28299 214 block_atimers ();
177c0ea7 215
9c2e3e8d
GM
216 if (t)
217 {
2503c8b1 218 struct atimer *p, *prev;
177c0ea7 219
2503c8b1 220 /* See if T is active. */
96013ba9 221 for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next)
2503c8b1
GM
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;
9c2e3e8d 235 }
177c0ea7 236
50b1039f 237 stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
9c2e3e8d 238 atimers = t;
2fe28299 239 unblock_atimers ();
9c2e3e8d
GM
240}
241
242
243/* Run all timers again, if some have been stopped with a call to
244 stop_other_atimers. */
245
e192d7d3 246static void
971de7fb 247run_all_atimers (void)
9c2e3e8d
GM
248{
249 if (stopped_atimers)
250 {
251 struct atimer *t = atimers;
50b1039f 252 struct atimer *next;
177c0ea7 253
2fe28299 254 block_atimers ();
9c2e3e8d
GM
255 atimers = stopped_atimers;
256 stopped_atimers = NULL;
177c0ea7 257
50b1039f
GM
258 while (t)
259 {
260 next = t->next;
261 schedule_atimer (t);
262 t = next;
263 }
177c0ea7 264
2fe28299 265 unblock_atimers ();
9c2e3e8d
GM
266 }
267}
268
269
e192d7d3 270/* A version of run_all_atimers suitable for a record_unwind_protect. */
9c2e3e8d
GM
271
272Lisp_Object
971de7fb 273unwind_stop_other_atimers (Lisp_Object dummy)
9c2e3e8d
GM
274{
275 run_all_atimers ();
276 return Qnil;
277}
278
279
e12489f9
GM
280/* Arrange for a SIGALRM to arrive when the next timer is ripe. */
281
282static void
971de7fb 283set_alarm (void)
e12489f9 284{
e12489f9
GM
285 if (atimers)
286 {
e12489f9
GM
287#ifdef HAVE_SETITIMER
288 struct itimerval it;
289#endif
290
291 /* Determine s/us till the next timer is ripe. */
e9a9ae03 292 EMACS_TIME now = current_emacs_time ();
e12489f9 293
e12489f9 294 /* Don't set the interval to 0; this disables the timer. */
e9a9ae03
PE
295 EMACS_TIME interval = (EMACS_TIME_LE (atimers->expiration, now)
296 ? make_emacs_time (0, 1000 * 1000)
297 : sub_emacs_time (atimers->expiration, now));
d35af63c
PE
298
299#ifdef HAVE_SETITIMER
177c0ea7 300
72af86bd 301 memset (&it, 0, sizeof it);
e9a9ae03 302 it.it_value = make_timeval (interval);
e12489f9
GM
303 setitimer (ITIMER_REAL, &it, 0);
304#else /* not HAVE_SETITIMER */
e9a9ae03 305 alarm (max (EMACS_SECS (interval), 1));
e12489f9
GM
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
971de7fb 316schedule_atimer (struct atimer *t)
e12489f9
GM
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;
177c0ea7 329
e12489f9
GM
330 t->next = a;
331}
332
170c80be 333static void
971de7fb 334run_timers (void)
e12489f9 335{
4d7e6e51 336 EMACS_TIME now = current_emacs_time ();
177c0ea7 337
4d7e6e51 338 while (atimers && EMACS_TIME_LE (atimers->expiration, now))
e12489f9 339 {
4d7e6e51 340 struct atimer *t = atimers;
e12489f9
GM
341 atimers = atimers->next;
342 t->fn (t);
177c0ea7 343
e12489f9
GM
344 if (t->type == ATIMER_CONTINUOUS)
345 {
e9a9ae03 346 t->expiration = add_emacs_time (now, t->interval);
e12489f9
GM
347 schedule_atimer (t);
348 }
349 else
350 {
351 t->next = free_atimers;
352 free_atimers = t;
353 }
e12489f9 354 }
177c0ea7 355
4d7e6e51 356 set_alarm ();
e12489f9
GM
357}
358
359
170c80be
JD
360/* Signal handler for SIGALRM. SIGNO is the signal number, i.e.
361 SIGALRM. */
362
20ef56db
PE
363static void
364handle_alarm_signal (int sig)
170c80be 365{
325530de 366 pending_signals = 1;
170c80be
JD
367}
368
369
4d7e6e51 370/* Do pending timers. */
e12489f9
GM
371
372void
971de7fb 373do_pending_atimers (void)
e12489f9 374{
4d7e6e51 375 if (atimers)
e12489f9 376 {
2fe28299 377 block_atimers ();
170c80be 378 run_timers ();
2fe28299 379 unblock_atimers ();
e12489f9
GM
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
b1bb8011 388turn_on_atimers (bool on)
e12489f9
GM
389{
390 if (on)
4d7e6e51 391 set_alarm ();
e12489f9
GM
392 else
393 alarm (0);
394}
395
396
397void
971de7fb 398init_atimer (void)
e12489f9 399{
2fe28299 400 struct sigaction action;
bcdf96ba 401 free_atimers = stopped_atimers = atimers = NULL;
325530de 402 /* pending_signals is initialized in init_keyboard.*/
4d7e6e51 403 emacs_sigaction_init (&action, handle_alarm_signal);
2fe28299 404 sigaction (SIGALRM, &action, 0);
e12489f9 405}