]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-event/sd-event.c
shared: fix coding-style for ring-buffer implementation
[thirdparty/systemd.git] / src / libsystemd / sd-event / sd-event.c
CommitLineData
fd38203a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <sys/epoll.h>
23#include <sys/timerfd.h>
24#include <sys/wait.h>
3022d74b 25#include <pthread.h>
fd38203a 26
afc6adb5 27#include "sd-id128.h"
cde93897 28#include "sd-daemon.h"
fd38203a 29#include "macro.h"
fd38203a
LP
30#include "prioq.h"
31#include "hashmap.h"
32#include "util.h"
33#include "time-util.h"
afc6adb5 34#include "missing.h"
6e9feda3 35#include "set.h"
a71fe8b8 36#include "list.h"
fd38203a
LP
37
38#include "sd-event.h"
39
15b38f93 40#define EPOLL_QUEUE_MAX 512U
c2ba3ad6 41#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
fd38203a
LP
42
43typedef enum EventSourceType {
44 SOURCE_IO,
6a0f1f6d
LP
45 SOURCE_TIME_REALTIME,
46 SOURCE_TIME_MONOTONIC,
47 SOURCE_TIME_REALTIME_ALARM,
48 SOURCE_TIME_BOOTTIME_ALARM,
fd38203a
LP
49 SOURCE_SIGNAL,
50 SOURCE_CHILD,
da7e457c 51 SOURCE_DEFER,
6e9feda3 52 SOURCE_POST,
6203e07a 53 SOURCE_EXIT,
6a0f1f6d 54 SOURCE_WATCHDOG,
a71fe8b8 55 _SOURCE_EVENT_SOURCE_TYPE_MAX,
6a0f1f6d 56 _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
fd38203a
LP
57} EventSourceType;
58
6a0f1f6d
LP
59#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
60
fd38203a 61struct sd_event_source {
da7e457c 62 unsigned n_ref;
fd38203a
LP
63
64 sd_event *event;
65 void *userdata;
718db961 66 sd_event_handler_t prepare;
fd38203a 67
6a0f1f6d 68 EventSourceType type:5;
baf76283 69 int enabled:3;
fd38203a 70 bool pending:1;
12179984 71 bool dispatching:1;
a71fe8b8 72 bool floating:1;
fd38203a 73
31927c16 74 int64_t priority;
fd38203a
LP
75 unsigned pending_index;
76 unsigned prepare_index;
77 unsigned pending_iteration;
78 unsigned prepare_iteration;
79
a71fe8b8
LP
80 LIST_FIELDS(sd_event_source, sources);
81
fd38203a
LP
82 union {
83 struct {
718db961 84 sd_event_io_handler_t callback;
fd38203a
LP
85 int fd;
86 uint32_t events;
87 uint32_t revents;
88 bool registered:1;
89 } io;
90 struct {
718db961 91 sd_event_time_handler_t callback;
c2ba3ad6
LP
92 usec_t next, accuracy;
93 unsigned earliest_index;
94 unsigned latest_index;
fd38203a
LP
95 } time;
96 struct {
718db961 97 sd_event_signal_handler_t callback;
fd38203a
LP
98 struct signalfd_siginfo siginfo;
99 int sig;
100 } signal;
101 struct {
718db961 102 sd_event_child_handler_t callback;
fd38203a
LP
103 siginfo_t siginfo;
104 pid_t pid;
105 int options;
106 } child;
107 struct {
718db961 108 sd_event_handler_t callback;
fd38203a 109 } defer;
6e9feda3
LP
110 struct {
111 sd_event_handler_t callback;
112 } post;
da7e457c 113 struct {
718db961 114 sd_event_handler_t callback;
da7e457c 115 unsigned prioq_index;
6203e07a 116 } exit;
fd38203a
LP
117 };
118};
119
6a0f1f6d
LP
120struct clock_data {
121 int fd;
122
123 /* For all clocks we maintain two priority queues each, one
124 * ordered for the earliest times the events may be
125 * dispatched, and one ordered by the latest times they must
126 * have been dispatched. The range between the top entries in
127 * the two prioqs is the time window we can freely schedule
128 * wakeups in */
129
130 Prioq *earliest;
131 Prioq *latest;
132 usec_t next;
133};
134
fd38203a 135struct sd_event {
da7e457c 136 unsigned n_ref;
fd38203a
LP
137
138 int epoll_fd;
139 int signal_fd;
cde93897 140 int watchdog_fd;
fd38203a
LP
141
142 Prioq *pending;
143 Prioq *prepare;
c2ba3ad6 144
6a0f1f6d
LP
145 /* timerfd_create() only supports these four clocks so far. We
146 * can add support for more clocks when the kernel learns to
147 * deal with them, too. */
148 struct clock_data realtime;
149 struct clock_data monotonic;
150 struct clock_data realtime_alarm;
151 struct clock_data boottime_alarm;
fd38203a 152
da7e457c
LP
153 usec_t perturb;
154
fd38203a
LP
155 sigset_t sigset;
156 sd_event_source **signal_sources;
157
158 Hashmap *child_sources;
baf76283 159 unsigned n_enabled_child_sources;
fd38203a 160
6e9feda3
LP
161 Set *post_sources;
162
6203e07a 163 Prioq *exit;
fd38203a 164
da7e457c 165 pid_t original_pid;
c2ba3ad6 166
da7e457c 167 unsigned iteration;
46e8c825 168 dual_timestamp timestamp;
6a0f1f6d 169 usec_t timestamp_boottime;
da7e457c 170 int state;
eaa3cbef 171
6203e07a 172 bool exit_requested:1;
da7e457c 173 bool need_process_child:1;
cde93897 174 bool watchdog:1;
afc6adb5 175
6203e07a
LP
176 int exit_code;
177
afc6adb5
LP
178 pid_t tid;
179 sd_event **default_event_ptr;
cde93897
LP
180
181 usec_t watchdog_last, watchdog_period;
15b38f93
LP
182
183 unsigned n_sources;
a71fe8b8
LP
184
185 LIST_HEAD(sd_event_source, sources);
fd38203a
LP
186};
187
a71fe8b8
LP
188static void source_disconnect(sd_event_source *s);
189
fd38203a
LP
190static int pending_prioq_compare(const void *a, const void *b) {
191 const sd_event_source *x = a, *y = b;
192
193 assert(x->pending);
194 assert(y->pending);
195
baf76283
LP
196 /* Enabled ones first */
197 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 198 return -1;
baf76283 199 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
200 return 1;
201
202 /* Lower priority values first */
203 if (x->priority < y->priority)
204 return -1;
205 if (x->priority > y->priority)
206 return 1;
207
208 /* Older entries first */
209 if (x->pending_iteration < y->pending_iteration)
210 return -1;
211 if (x->pending_iteration > y->pending_iteration)
212 return 1;
213
214 /* Stability for the rest */
215 if (x < y)
216 return -1;
dfcd88f6 217 if (x > y)
fd38203a
LP
218 return 1;
219
220 return 0;
221}
222
223static int prepare_prioq_compare(const void *a, const void *b) {
224 const sd_event_source *x = a, *y = b;
225
226 assert(x->prepare);
227 assert(y->prepare);
228
229 /* Move most recently prepared ones last, so that we can stop
230 * preparing as soon as we hit one that has already been
231 * prepared in the current iteration */
232 if (x->prepare_iteration < y->prepare_iteration)
233 return -1;
234 if (x->prepare_iteration > y->prepare_iteration)
235 return 1;
236
baf76283
LP
237 /* Enabled ones first */
238 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 239 return -1;
baf76283 240 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
241 return 1;
242
243 /* Lower priority values first */
244 if (x->priority < y->priority)
245 return -1;
246 if (x->priority > y->priority)
247 return 1;
248
249 /* Stability for the rest */
250 if (x < y)
251 return -1;
dfcd88f6 252 if (x > y)
fd38203a
LP
253 return 1;
254
255 return 0;
256}
257
c2ba3ad6 258static int earliest_time_prioq_compare(const void *a, const void *b) {
fd38203a
LP
259 const sd_event_source *x = a, *y = b;
260
6a0f1f6d
LP
261 assert(EVENT_SOURCE_IS_TIME(x->type));
262 assert(x->type == y->type);
fd38203a 263
baf76283
LP
264 /* Enabled ones first */
265 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 266 return -1;
baf76283 267 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
268 return 1;
269
270 /* Move the pending ones to the end */
271 if (!x->pending && y->pending)
272 return -1;
273 if (x->pending && !y->pending)
274 return 1;
275
276 /* Order by time */
277 if (x->time.next < y->time.next)
278 return -1;
279 if (x->time.next > y->time.next)
a99badf5 280 return 1;
fd38203a
LP
281
282 /* Stability for the rest */
283 if (x < y)
284 return -1;
dfcd88f6 285 if (x > y)
fd38203a
LP
286 return 1;
287
288 return 0;
289}
290
c2ba3ad6
LP
291static int latest_time_prioq_compare(const void *a, const void *b) {
292 const sd_event_source *x = a, *y = b;
293
6a0f1f6d
LP
294 assert(EVENT_SOURCE_IS_TIME(x->type));
295 assert(x->type == y->type);
c2ba3ad6 296
baf76283
LP
297 /* Enabled ones first */
298 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
c2ba3ad6 299 return -1;
baf76283 300 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
c2ba3ad6
LP
301 return 1;
302
303 /* Move the pending ones to the end */
304 if (!x->pending && y->pending)
305 return -1;
306 if (x->pending && !y->pending)
307 return 1;
308
309 /* Order by time */
310 if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
311 return -1;
312 if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
a99badf5 313 return 1;
c2ba3ad6
LP
314
315 /* Stability for the rest */
316 if (x < y)
317 return -1;
318 if (x > y)
319 return 1;
320
321 return 0;
322}
323
6203e07a 324static int exit_prioq_compare(const void *a, const void *b) {
da7e457c
LP
325 const sd_event_source *x = a, *y = b;
326
6203e07a
LP
327 assert(x->type == SOURCE_EXIT);
328 assert(y->type == SOURCE_EXIT);
da7e457c 329
baf76283
LP
330 /* Enabled ones first */
331 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
da7e457c 332 return -1;
baf76283 333 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
da7e457c
LP
334 return 1;
335
336 /* Lower priority values first */
337 if (x->priority < y->priority)
338 return -1;
339 if (x->priority > y->priority)
340 return 1;
341
342 /* Stability for the rest */
343 if (x < y)
344 return -1;
345 if (x > y)
346 return 1;
347
348 return 0;
349}
350
6a0f1f6d
LP
351static void free_clock_data(struct clock_data *d) {
352 assert(d);
353
354 safe_close(d->fd);
355 prioq_free(d->earliest);
356 prioq_free(d->latest);
357}
358
fd38203a 359static void event_free(sd_event *e) {
a71fe8b8
LP
360 sd_event_source *s;
361
fd38203a 362 assert(e);
a71fe8b8
LP
363
364 while ((s = e->sources)) {
365 assert(s->floating);
366 source_disconnect(s);
367 sd_event_source_unref(s);
368 }
369
15b38f93 370 assert(e->n_sources == 0);
fd38203a 371
afc6adb5
LP
372 if (e->default_event_ptr)
373 *(e->default_event_ptr) = NULL;
374
03e334a1
LP
375 safe_close(e->epoll_fd);
376 safe_close(e->signal_fd);
03e334a1 377 safe_close(e->watchdog_fd);
cde93897 378
6a0f1f6d
LP
379 free_clock_data(&e->realtime);
380 free_clock_data(&e->monotonic);
381 free_clock_data(&e->realtime_alarm);
382 free_clock_data(&e->boottime_alarm);
383
fd38203a
LP
384 prioq_free(e->pending);
385 prioq_free(e->prepare);
6203e07a 386 prioq_free(e->exit);
fd38203a
LP
387
388 free(e->signal_sources);
389
390 hashmap_free(e->child_sources);
6e9feda3 391 set_free(e->post_sources);
fd38203a
LP
392 free(e);
393}
394
f7262a9f 395_public_ int sd_event_new(sd_event** ret) {
fd38203a
LP
396 sd_event *e;
397 int r;
398
305f78bf 399 assert_return(ret, -EINVAL);
fd38203a
LP
400
401 e = new0(sd_event, 1);
402 if (!e)
403 return -ENOMEM;
404
da7e457c 405 e->n_ref = 1;
6a0f1f6d
LP
406 e->signal_fd = e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
407 e->realtime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = (usec_t) -1;
eaa3cbef 408 e->original_pid = getpid();
6a0f1f6d 409 e->perturb = (usec_t) -1;
fd38203a
LP
410
411 assert_se(sigemptyset(&e->sigset) == 0);
412
413 e->pending = prioq_new(pending_prioq_compare);
414 if (!e->pending) {
415 r = -ENOMEM;
416 goto fail;
417 }
418
419 e->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
420 if (e->epoll_fd < 0) {
421 r = -errno;
422 goto fail;
423 }
424
425 *ret = e;
426 return 0;
427
428fail:
429 event_free(e);
430 return r;
431}
432
f7262a9f 433_public_ sd_event* sd_event_ref(sd_event *e) {
305f78bf 434 assert_return(e, NULL);
fd38203a 435
da7e457c
LP
436 assert(e->n_ref >= 1);
437 e->n_ref++;
fd38203a
LP
438
439 return e;
440}
441
f7262a9f 442_public_ sd_event* sd_event_unref(sd_event *e) {
5b1bc83f
LP
443
444 if (!e)
445 return NULL;
fd38203a 446
da7e457c
LP
447 assert(e->n_ref >= 1);
448 e->n_ref--;
449
450 if (e->n_ref <= 0)
fd38203a
LP
451 event_free(e);
452
453 return NULL;
454}
455
eaa3cbef
LP
456static bool event_pid_changed(sd_event *e) {
457 assert(e);
458
459 /* We don't support people creating am event loop and keeping
460 * it around over a fork(). Let's complain. */
461
462 return e->original_pid != getpid();
463}
464
fd38203a
LP
465static int source_io_unregister(sd_event_source *s) {
466 int r;
467
468 assert(s);
469 assert(s->type == SOURCE_IO);
470
471 if (!s->io.registered)
472 return 0;
473
474 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL);
475 if (r < 0)
476 return -errno;
477
478 s->io.registered = false;
479 return 0;
480}
481
305f78bf
LP
482static int source_io_register(
483 sd_event_source *s,
484 int enabled,
485 uint32_t events) {
486
fd38203a
LP
487 struct epoll_event ev = {};
488 int r;
489
490 assert(s);
491 assert(s->type == SOURCE_IO);
baf76283 492 assert(enabled != SD_EVENT_OFF);
fd38203a
LP
493
494 ev.events = events;
495 ev.data.ptr = s;
496
baf76283 497 if (enabled == SD_EVENT_ONESHOT)
fd38203a
LP
498 ev.events |= EPOLLONESHOT;
499
500 if (s->io.registered)
501 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
502 else
503 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev);
504
505 if (r < 0)
506 return -errno;
507
508 s->io.registered = true;
509
510 return 0;
511}
512
6a0f1f6d
LP
513static clockid_t event_source_type_to_clock(EventSourceType t) {
514
515 switch (t) {
516
517 case SOURCE_TIME_REALTIME:
518 return CLOCK_REALTIME;
519
520 case SOURCE_TIME_MONOTONIC:
521 return CLOCK_MONOTONIC;
522
523 case SOURCE_TIME_REALTIME_ALARM:
524 return CLOCK_REALTIME_ALARM;
525
526 case SOURCE_TIME_BOOTTIME_ALARM:
527 return CLOCK_BOOTTIME_ALARM;
528
529 default:
530 return (clockid_t) -1;
531 }
532}
533
534static EventSourceType clock_to_event_source_type(clockid_t clock) {
535
536 switch (clock) {
537
538 case CLOCK_REALTIME:
539 return SOURCE_TIME_REALTIME;
540
541 case CLOCK_MONOTONIC:
542 return SOURCE_TIME_MONOTONIC;
543
544 case CLOCK_REALTIME_ALARM:
545 return SOURCE_TIME_REALTIME_ALARM;
546
547 case CLOCK_BOOTTIME_ALARM:
548 return SOURCE_TIME_BOOTTIME_ALARM;
549
550 default:
551 return _SOURCE_EVENT_SOURCE_TYPE_INVALID;
552 }
553}
554
555static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) {
556 assert(e);
557
558 switch (t) {
559
560 case SOURCE_TIME_REALTIME:
561 return &e->realtime;
562
563 case SOURCE_TIME_MONOTONIC:
564 return &e->monotonic;
565
566 case SOURCE_TIME_REALTIME_ALARM:
567 return &e->realtime_alarm;
568
569 case SOURCE_TIME_BOOTTIME_ALARM:
570 return &e->boottime_alarm;
571
572 default:
573 return NULL;
574 }
575}
576
a71fe8b8
LP
577static void source_disconnect(sd_event_source *s) {
578 sd_event *event;
579
fd38203a
LP
580 assert(s);
581
a71fe8b8
LP
582 if (!s->event)
583 return;
15b38f93 584
a71fe8b8 585 assert(s->event->n_sources > 0);
fd38203a 586
a71fe8b8 587 switch (s->type) {
fd38203a 588
a71fe8b8
LP
589 case SOURCE_IO:
590 if (s->io.fd >= 0)
591 source_io_unregister(s);
fd38203a 592
a71fe8b8 593 break;
6a0f1f6d 594
a71fe8b8
LP
595 case SOURCE_TIME_REALTIME:
596 case SOURCE_TIME_MONOTONIC:
597 case SOURCE_TIME_REALTIME_ALARM:
598 case SOURCE_TIME_BOOTTIME_ALARM: {
599 struct clock_data *d;
fd38203a 600
a71fe8b8
LP
601 d = event_get_clock_data(s->event, s->type);
602 assert(d);
603
604 prioq_remove(d->earliest, s, &s->time.earliest_index);
605 prioq_remove(d->latest, s, &s->time.latest_index);
606 break;
607 }
608
609 case SOURCE_SIGNAL:
610 if (s->signal.sig > 0) {
611 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0)
612 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
613
614 if (s->event->signal_sources)
615 s->event->signal_sources[s->signal.sig] = NULL;
6a0f1f6d 616 }
fd38203a 617
a71fe8b8 618 break;
fd38203a 619
a71fe8b8
LP
620 case SOURCE_CHILD:
621 if (s->child.pid > 0) {
622 if (s->enabled != SD_EVENT_OFF) {
623 assert(s->event->n_enabled_child_sources > 0);
624 s->event->n_enabled_child_sources--;
fd38203a
LP
625 }
626
a71fe8b8
LP
627 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD])
628 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
fd38203a 629
a71fe8b8
LP
630 hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
631 }
fd38203a 632
a71fe8b8 633 break;
fd38203a 634
a71fe8b8
LP
635 case SOURCE_DEFER:
636 /* nothing */
637 break;
fd38203a 638
a71fe8b8
LP
639 case SOURCE_POST:
640 set_remove(s->event->post_sources, s);
641 break;
da7e457c 642
a71fe8b8
LP
643 case SOURCE_EXIT:
644 prioq_remove(s->event->exit, s, &s->exit.prioq_index);
645 break;
0eb2e0e3 646
a71fe8b8
LP
647 default:
648 assert_not_reached("Wut? I shouldn't exist.");
649 }
6e9feda3 650
a71fe8b8
LP
651 if (s->pending)
652 prioq_remove(s->event->pending, s, &s->pending_index);
9d3e3aa5 653
a71fe8b8
LP
654 if (s->prepare)
655 prioq_remove(s->event->prepare, s, &s->prepare_index);
fd38203a 656
a71fe8b8 657 event = s->event;
fd38203a 658
a71fe8b8
LP
659 s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID;
660 s->event = NULL;
661 LIST_REMOVE(sources, event->sources, s);
662 event->n_sources--;
fd38203a 663
a71fe8b8
LP
664 if (!s->floating)
665 sd_event_unref(event);
666}
667
668static void source_free(sd_event_source *s) {
669 assert(s);
fd38203a 670
a71fe8b8 671 source_disconnect(s);
fd38203a
LP
672 free(s);
673}
674
675static int source_set_pending(sd_event_source *s, bool b) {
676 int r;
677
678 assert(s);
6203e07a 679 assert(s->type != SOURCE_EXIT);
fd38203a
LP
680
681 if (s->pending == b)
682 return 0;
683
684 s->pending = b;
685
686 if (b) {
687 s->pending_iteration = s->event->iteration;
688
689 r = prioq_put(s->event->pending, s, &s->pending_index);
690 if (r < 0) {
691 s->pending = false;
692 return r;
693 }
694 } else
695 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
696
6a0f1f6d
LP
697 if (EVENT_SOURCE_IS_TIME(s->type)) {
698 struct clock_data *d;
699
700 d = event_get_clock_data(s->event, s->type);
701 assert(d);
702
703 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
704 prioq_reshuffle(d->latest, s, &s->time.latest_index);
2576a19e
LP
705 }
706
fd38203a
LP
707 return 0;
708}
709
a71fe8b8 710static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) {
fd38203a
LP
711 sd_event_source *s;
712
713 assert(e);
714
715 s = new0(sd_event_source, 1);
716 if (!s)
717 return NULL;
718
da7e457c 719 s->n_ref = 1;
a71fe8b8 720 s->event = e;
4a134c49 721 s->floating = floating;
fd38203a 722 s->type = type;
fd38203a 723 s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
a71fe8b8
LP
724
725 if (!floating)
726 sd_event_ref(e);
fd38203a 727
a71fe8b8 728 LIST_PREPEND(sources, e->sources, s);
15b38f93
LP
729 e->n_sources ++;
730
fd38203a
LP
731 return s;
732}
733
f7262a9f 734_public_ int sd_event_add_io(
fd38203a 735 sd_event *e,
151b9b96 736 sd_event_source **ret,
fd38203a
LP
737 int fd,
738 uint32_t events,
718db961 739 sd_event_io_handler_t callback,
151b9b96 740 void *userdata) {
fd38203a
LP
741
742 sd_event_source *s;
743 int r;
744
305f78bf
LP
745 assert_return(e, -EINVAL);
746 assert_return(fd >= 0, -EINVAL);
2a16a986 747 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
305f78bf 748 assert_return(callback, -EINVAL);
da7e457c 749 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 750 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 751
a71fe8b8 752 s = source_new(e, !ret, SOURCE_IO);
fd38203a
LP
753 if (!s)
754 return -ENOMEM;
755
756 s->io.fd = fd;
757 s->io.events = events;
758 s->io.callback = callback;
759 s->userdata = userdata;
baf76283 760 s->enabled = SD_EVENT_ON;
fd38203a 761
baf76283 762 r = source_io_register(s, s->enabled, events);
fd38203a
LP
763 if (r < 0) {
764 source_free(s);
765 return -errno;
766 }
767
a71fe8b8
LP
768 if (ret)
769 *ret = s;
770
fd38203a
LP
771 return 0;
772}
773
52444dc4
LP
774static void initialize_perturb(sd_event *e) {
775 sd_id128_t bootid = {};
776
777 /* When we sleep for longer, we try to realign the wakeup to
778 the same time wihtin each minute/second/250ms, so that
779 events all across the system can be coalesced into a single
780 CPU wakeup. However, let's take some system-specific
781 randomness for this value, so that in a network of systems
782 with synced clocks timer events are distributed a
783 bit. Here, we calculate a perturbation usec offset from the
784 boot ID. */
785
786 if (_likely_(e->perturb != (usec_t) -1))
787 return;
788
789 if (sd_id128_get_boot(&bootid) >= 0)
790 e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE;
791}
792
fd38203a
LP
793static int event_setup_timer_fd(
794 sd_event *e,
6a0f1f6d
LP
795 struct clock_data *d,
796 clockid_t clock) {
fd38203a
LP
797
798 struct epoll_event ev = {};
799 int r, fd;
800
801 assert(e);
6a0f1f6d 802 assert(d);
fd38203a 803
6a0f1f6d 804 if (_likely_(d->fd >= 0))
fd38203a
LP
805 return 0;
806
6a0f1f6d 807 fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC);
fd38203a
LP
808 if (fd < 0)
809 return -errno;
810
811 ev.events = EPOLLIN;
6a0f1f6d 812 ev.data.ptr = INT_TO_PTR(clock_to_event_source_type(clock));
fd38203a
LP
813
814 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
815 if (r < 0) {
03e334a1 816 safe_close(fd);
fd38203a
LP
817 return -errno;
818 }
819
6a0f1f6d 820 d->fd = fd;
fd38203a
LP
821 return 0;
822}
823
6a0f1f6d 824_public_ int sd_event_add_time(
fd38203a 825 sd_event *e,
151b9b96 826 sd_event_source **ret,
6a0f1f6d 827 clockid_t clock,
fd38203a 828 uint64_t usec,
c2ba3ad6 829 uint64_t accuracy,
718db961 830 sd_event_time_handler_t callback,
151b9b96 831 void *userdata) {
fd38203a 832
6a0f1f6d 833 EventSourceType type;
fd38203a 834 sd_event_source *s;
6a0f1f6d 835 struct clock_data *d;
fd38203a
LP
836 int r;
837
305f78bf 838 assert_return(e, -EINVAL);
305f78bf
LP
839 assert_return(usec != (uint64_t) -1, -EINVAL);
840 assert_return(accuracy != (uint64_t) -1, -EINVAL);
6a0f1f6d 841 assert_return(callback, -EINVAL);
da7e457c 842 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 843 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 844
6a0f1f6d
LP
845 type = clock_to_event_source_type(clock);
846 assert_return(type >= 0, -ENOTSUP);
847
848 d = event_get_clock_data(e, type);
849 assert(d);
c2ba3ad6 850
6a0f1f6d
LP
851 if (!d->earliest) {
852 d->earliest = prioq_new(earliest_time_prioq_compare);
853 if (!d->earliest)
c2ba3ad6
LP
854 return -ENOMEM;
855 }
fd38203a 856
6a0f1f6d
LP
857 if (!d->latest) {
858 d->latest = prioq_new(latest_time_prioq_compare);
859 if (!d->latest)
fd38203a
LP
860 return -ENOMEM;
861 }
862
6a0f1f6d
LP
863 if (d->fd < 0) {
864 r = event_setup_timer_fd(e, d, clock);
fd38203a
LP
865 if (r < 0)
866 return r;
867 }
868
a71fe8b8 869 s = source_new(e, !ret, type);
fd38203a
LP
870 if (!s)
871 return -ENOMEM;
872
873 s->time.next = usec;
c2ba3ad6 874 s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy;
fd38203a 875 s->time.callback = callback;
da7e457c 876 s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL;
fd38203a 877 s->userdata = userdata;
baf76283 878 s->enabled = SD_EVENT_ONESHOT;
fd38203a 879
6a0f1f6d 880 r = prioq_put(d->earliest, s, &s->time.earliest_index);
c2ba3ad6
LP
881 if (r < 0)
882 goto fail;
883
6a0f1f6d 884 r = prioq_put(d->latest, s, &s->time.latest_index);
c2ba3ad6
LP
885 if (r < 0)
886 goto fail;
fd38203a 887
a71fe8b8
LP
888 if (ret)
889 *ret = s;
890
fd38203a 891 return 0;
c2ba3ad6
LP
892
893fail:
894 source_free(s);
895 return r;
fd38203a
LP
896}
897
fd38203a
LP
898static int event_update_signal_fd(sd_event *e) {
899 struct epoll_event ev = {};
900 bool add_to_epoll;
901 int r;
902
903 assert(e);
904
905 add_to_epoll = e->signal_fd < 0;
906
907 r = signalfd(e->signal_fd, &e->sigset, SFD_NONBLOCK|SFD_CLOEXEC);
908 if (r < 0)
909 return -errno;
910
911 e->signal_fd = r;
912
913 if (!add_to_epoll)
914 return 0;
915
916 ev.events = EPOLLIN;
917 ev.data.ptr = INT_TO_PTR(SOURCE_SIGNAL);
918
919 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->signal_fd, &ev);
920 if (r < 0) {
03e334a1 921 e->signal_fd = safe_close(e->signal_fd);
fd38203a
LP
922 return -errno;
923 }
924
925 return 0;
926}
927
59bc1fd7
LP
928static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
929 assert(s);
930
931 return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
932}
933
f7262a9f 934_public_ int sd_event_add_signal(
305f78bf 935 sd_event *e,
151b9b96 936 sd_event_source **ret,
305f78bf 937 int sig,
718db961 938 sd_event_signal_handler_t callback,
151b9b96 939 void *userdata) {
305f78bf 940
fd38203a 941 sd_event_source *s;
3022d74b 942 sigset_t ss;
fd38203a
LP
943 int r;
944
305f78bf
LP
945 assert_return(e, -EINVAL);
946 assert_return(sig > 0, -EINVAL);
947 assert_return(sig < _NSIG, -EINVAL);
da7e457c 948 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 949 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 950
59bc1fd7
LP
951 if (!callback)
952 callback = signal_exit_callback;
953
3022d74b
LP
954 r = pthread_sigmask(SIG_SETMASK, NULL, &ss);
955 if (r < 0)
956 return -errno;
957
958 if (!sigismember(&ss, sig))
959 return -EBUSY;
960
fd38203a
LP
961 if (!e->signal_sources) {
962 e->signal_sources = new0(sd_event_source*, _NSIG);
963 if (!e->signal_sources)
964 return -ENOMEM;
965 } else if (e->signal_sources[sig])
966 return -EBUSY;
967
a71fe8b8 968 s = source_new(e, !ret, SOURCE_SIGNAL);
fd38203a
LP
969 if (!s)
970 return -ENOMEM;
971
972 s->signal.sig = sig;
973 s->signal.callback = callback;
974 s->userdata = userdata;
baf76283 975 s->enabled = SD_EVENT_ON;
fd38203a
LP
976
977 e->signal_sources[sig] = s;
978 assert_se(sigaddset(&e->sigset, sig) == 0);
979
baf76283 980 if (sig != SIGCHLD || e->n_enabled_child_sources == 0) {
fd38203a
LP
981 r = event_update_signal_fd(e);
982 if (r < 0) {
983 source_free(s);
984 return r;
985 }
986 }
987
a71fe8b8
LP
988 if (ret)
989 *ret = s;
990
fd38203a
LP
991 return 0;
992}
993
f7262a9f 994_public_ int sd_event_add_child(
305f78bf 995 sd_event *e,
151b9b96 996 sd_event_source **ret,
305f78bf
LP
997 pid_t pid,
998 int options,
718db961 999 sd_event_child_handler_t callback,
151b9b96 1000 void *userdata) {
305f78bf 1001
fd38203a
LP
1002 sd_event_source *s;
1003 int r;
1004
305f78bf
LP
1005 assert_return(e, -EINVAL);
1006 assert_return(pid > 1, -EINVAL);
1007 assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
1008 assert_return(options != 0, -EINVAL);
1009 assert_return(callback, -EINVAL);
da7e457c 1010 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1011 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
1012
1013 r = hashmap_ensure_allocated(&e->child_sources, trivial_hash_func, trivial_compare_func);
1014 if (r < 0)
1015 return r;
1016
1017 if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
1018 return -EBUSY;
1019
a71fe8b8 1020 s = source_new(e, !ret, SOURCE_CHILD);
fd38203a
LP
1021 if (!s)
1022 return -ENOMEM;
1023
1024 s->child.pid = pid;
1025 s->child.options = options;
1026 s->child.callback = callback;
1027 s->userdata = userdata;
baf76283 1028 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
1029
1030 r = hashmap_put(e->child_sources, INT_TO_PTR(pid), s);
1031 if (r < 0) {
1032 source_free(s);
1033 return r;
1034 }
1035
baf76283 1036 e->n_enabled_child_sources ++;
fd38203a
LP
1037
1038 assert_se(sigaddset(&e->sigset, SIGCHLD) == 0);
1039
1040 if (!e->signal_sources || !e->signal_sources[SIGCHLD]) {
1041 r = event_update_signal_fd(e);
1042 if (r < 0) {
1043 source_free(s);
1044 return -errno;
1045 }
1046 }
1047
c2ba3ad6
LP
1048 e->need_process_child = true;
1049
a71fe8b8
LP
1050 if (ret)
1051 *ret = s;
1052
fd38203a
LP
1053 return 0;
1054}
1055
f7262a9f 1056_public_ int sd_event_add_defer(
305f78bf 1057 sd_event *e,
151b9b96 1058 sd_event_source **ret,
718db961 1059 sd_event_handler_t callback,
151b9b96 1060 void *userdata) {
305f78bf 1061
fd38203a
LP
1062 sd_event_source *s;
1063 int r;
1064
305f78bf
LP
1065 assert_return(e, -EINVAL);
1066 assert_return(callback, -EINVAL);
da7e457c 1067 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1068 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1069
a71fe8b8 1070 s = source_new(e, !ret, SOURCE_DEFER);
fd38203a
LP
1071 if (!s)
1072 return -ENOMEM;
1073
1074 s->defer.callback = callback;
1075 s->userdata = userdata;
baf76283 1076 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
1077
1078 r = source_set_pending(s, true);
1079 if (r < 0) {
1080 source_free(s);
1081 return r;
1082 }
1083
a71fe8b8
LP
1084 if (ret)
1085 *ret = s;
1086
fd38203a
LP
1087 return 0;
1088}
1089
6e9feda3
LP
1090_public_ int sd_event_add_post(
1091 sd_event *e,
1092 sd_event_source **ret,
1093 sd_event_handler_t callback,
1094 void *userdata) {
1095
1096 sd_event_source *s;
1097 int r;
1098
1099 assert_return(e, -EINVAL);
1100 assert_return(callback, -EINVAL);
6e9feda3
LP
1101 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1102 assert_return(!event_pid_changed(e), -ECHILD);
1103
1104 r = set_ensure_allocated(&e->post_sources, trivial_hash_func, trivial_compare_func);
1105 if (r < 0)
1106 return r;
1107
a71fe8b8 1108 s = source_new(e, !ret, SOURCE_POST);
6e9feda3
LP
1109 if (!s)
1110 return -ENOMEM;
1111
1112 s->post.callback = callback;
1113 s->userdata = userdata;
1114 s->enabled = SD_EVENT_ON;
1115
1116 r = set_put(e->post_sources, s);
1117 if (r < 0) {
1118 source_free(s);
1119 return r;
1120 }
1121
a71fe8b8
LP
1122 if (ret)
1123 *ret = s;
1124
6e9feda3
LP
1125 return 0;
1126}
1127
6203e07a 1128_public_ int sd_event_add_exit(
305f78bf 1129 sd_event *e,
151b9b96 1130 sd_event_source **ret,
718db961 1131 sd_event_handler_t callback,
151b9b96 1132 void *userdata) {
305f78bf 1133
da7e457c
LP
1134 sd_event_source *s;
1135 int r;
1136
1137 assert_return(e, -EINVAL);
1138 assert_return(callback, -EINVAL);
1139 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1140 assert_return(!event_pid_changed(e), -ECHILD);
1141
6203e07a
LP
1142 if (!e->exit) {
1143 e->exit = prioq_new(exit_prioq_compare);
1144 if (!e->exit)
da7e457c
LP
1145 return -ENOMEM;
1146 }
1147
a71fe8b8 1148 s = source_new(e, !ret, SOURCE_EXIT);
fd38203a 1149 if (!s)
da7e457c 1150 return -ENOMEM;
fd38203a 1151
6203e07a 1152 s->exit.callback = callback;
da7e457c 1153 s->userdata = userdata;
6203e07a 1154 s->exit.prioq_index = PRIOQ_IDX_NULL;
baf76283 1155 s->enabled = SD_EVENT_ONESHOT;
da7e457c 1156
6203e07a 1157 r = prioq_put(s->event->exit, s, &s->exit.prioq_index);
da7e457c
LP
1158 if (r < 0) {
1159 source_free(s);
1160 return r;
1161 }
1162
a71fe8b8
LP
1163 if (ret)
1164 *ret = s;
1165
da7e457c
LP
1166 return 0;
1167}
1168
f7262a9f 1169_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
da7e457c
LP
1170 assert_return(s, NULL);
1171
1172 assert(s->n_ref >= 1);
1173 s->n_ref++;
fd38203a
LP
1174
1175 return s;
1176}
1177
f7262a9f 1178_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
5b1bc83f
LP
1179
1180 if (!s)
1181 return NULL;
fd38203a 1182
da7e457c
LP
1183 assert(s->n_ref >= 1);
1184 s->n_ref--;
1185
12179984
LP
1186 if (s->n_ref <= 0) {
1187 /* Here's a special hack: when we are called from a
1188 * dispatch handler we won't free the event source
1189 * immediately, but we will detach the fd from the
1190 * epoll. This way it is safe for the caller to unref
1191 * the event source and immediately close the fd, but
1192 * we still retain a valid event source object after
1193 * the callback. */
1194
1195 if (s->dispatching) {
1196 if (s->type == SOURCE_IO)
1197 source_io_unregister(s);
a71fe8b8
LP
1198
1199 source_disconnect(s);
12179984
LP
1200 } else
1201 source_free(s);
1202 }
fd38203a
LP
1203
1204 return NULL;
1205}
1206
adcc4ca3 1207_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
305f78bf 1208 assert_return(s, NULL);
eaa3cbef
LP
1209
1210 return s->event;
1211}
1212
f7262a9f 1213_public_ int sd_event_source_get_pending(sd_event_source *s) {
305f78bf 1214 assert_return(s, -EINVAL);
6203e07a 1215 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c 1216 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1217 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1218
1219 return s->pending;
1220}
1221
f7262a9f 1222_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
305f78bf
LP
1223 assert_return(s, -EINVAL);
1224 assert_return(s->type == SOURCE_IO, -EDOM);
1225 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1226
1227 return s->io.fd;
1228}
1229
30caf8f3
LP
1230_public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) {
1231 int r;
1232
1233 assert_return(s, -EINVAL);
1234 assert_return(fd >= 0, -EINVAL);
1235 assert_return(s->type == SOURCE_IO, -EDOM);
1236 assert_return(!event_pid_changed(s->event), -ECHILD);
1237
1238 if (s->io.fd == fd)
1239 return 0;
1240
1241 if (s->enabled == SD_EVENT_OFF) {
1242 s->io.fd = fd;
1243 s->io.registered = false;
1244 } else {
1245 int saved_fd;
1246
1247 saved_fd = s->io.fd;
1248 assert(s->io.registered);
1249
1250 s->io.fd = fd;
1251 s->io.registered = false;
1252
1253 r = source_io_register(s, s->enabled, s->io.events);
1254 if (r < 0) {
1255 s->io.fd = saved_fd;
1256 s->io.registered = true;
1257 return r;
1258 }
1259
1260 epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL);
1261 }
1262
1263 return 0;
1264}
1265
f7262a9f 1266_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
305f78bf
LP
1267 assert_return(s, -EINVAL);
1268 assert_return(events, -EINVAL);
1269 assert_return(s->type == SOURCE_IO, -EDOM);
1270 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1271
1272 *events = s->io.events;
1273 return 0;
1274}
1275
f7262a9f 1276_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
fd38203a
LP
1277 int r;
1278
305f78bf
LP
1279 assert_return(s, -EINVAL);
1280 assert_return(s->type == SOURCE_IO, -EDOM);
2a16a986 1281 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
da7e457c 1282 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1283 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1284
1285 if (s->io.events == events)
1286 return 0;
1287
baf76283 1288 if (s->enabled != SD_EVENT_OFF) {
e4715127 1289 r = source_io_register(s, s->enabled, events);
fd38203a
LP
1290 if (r < 0)
1291 return r;
1292 }
1293
1294 s->io.events = events;
503f39c3 1295 source_set_pending(s, false);
fd38203a
LP
1296
1297 return 0;
1298}
1299
f7262a9f 1300_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
305f78bf
LP
1301 assert_return(s, -EINVAL);
1302 assert_return(revents, -EINVAL);
1303 assert_return(s->type == SOURCE_IO, -EDOM);
1304 assert_return(s->pending, -ENODATA);
1305 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1306
1307 *revents = s->io.revents;
1308 return 0;
1309}
1310
f7262a9f 1311_public_ int sd_event_source_get_signal(sd_event_source *s) {
305f78bf
LP
1312 assert_return(s, -EINVAL);
1313 assert_return(s->type == SOURCE_SIGNAL, -EDOM);
1314 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1315
1316 return s->signal.sig;
1317}
1318
31927c16 1319_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) {
305f78bf
LP
1320 assert_return(s, -EINVAL);
1321 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1322
1323 return s->priority;
1324}
1325
31927c16 1326_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) {
305f78bf 1327 assert_return(s, -EINVAL);
da7e457c 1328 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1329 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1330
1331 if (s->priority == priority)
1332 return 0;
1333
1334 s->priority = priority;
1335
1336 if (s->pending)
c2ba3ad6 1337 prioq_reshuffle(s->event->pending, s, &s->pending_index);
fd38203a
LP
1338
1339 if (s->prepare)
c2ba3ad6 1340 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
fd38203a 1341
6203e07a
LP
1342 if (s->type == SOURCE_EXIT)
1343 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf 1344
fd38203a
LP
1345 return 0;
1346}
1347
f7262a9f 1348_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
305f78bf
LP
1349 assert_return(s, -EINVAL);
1350 assert_return(m, -EINVAL);
1351 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1352
baf76283 1353 *m = s->enabled;
fd38203a
LP
1354 return 0;
1355}
1356
f7262a9f 1357_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
fd38203a
LP
1358 int r;
1359
305f78bf
LP
1360 assert_return(s, -EINVAL);
1361 assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL);
305f78bf 1362 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1363
cc567911
LP
1364 /* If we are dead anyway, we are fine with turning off
1365 * sources, but everything else needs to fail. */
1366 if (s->event->state == SD_EVENT_FINISHED)
1367 return m == SD_EVENT_OFF ? 0 : -ESTALE;
1368
baf76283 1369 if (s->enabled == m)
fd38203a
LP
1370 return 0;
1371
baf76283 1372 if (m == SD_EVENT_OFF) {
fd38203a
LP
1373
1374 switch (s->type) {
1375
1376 case SOURCE_IO:
1377 r = source_io_unregister(s);
1378 if (r < 0)
1379 return r;
1380
baf76283 1381 s->enabled = m;
fd38203a
LP
1382 break;
1383
6a0f1f6d
LP
1384 case SOURCE_TIME_REALTIME:
1385 case SOURCE_TIME_MONOTONIC:
1386 case SOURCE_TIME_REALTIME_ALARM:
1387 case SOURCE_TIME_BOOTTIME_ALARM: {
1388 struct clock_data *d;
fd38203a 1389
baf76283 1390 s->enabled = m;
6a0f1f6d
LP
1391 d = event_get_clock_data(s->event, s->type);
1392 assert(d);
1393
1394 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1395 prioq_reshuffle(d->latest, s, &s->time.latest_index);
fd38203a 1396 break;
6a0f1f6d 1397 }
fd38203a
LP
1398
1399 case SOURCE_SIGNAL:
baf76283
LP
1400 s->enabled = m;
1401 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1402 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
1403 event_update_signal_fd(s->event);
1404 }
1405
1406 break;
1407
1408 case SOURCE_CHILD:
baf76283 1409 s->enabled = m;
fd38203a 1410
baf76283
LP
1411 assert(s->event->n_enabled_child_sources > 0);
1412 s->event->n_enabled_child_sources--;
fd38203a
LP
1413
1414 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1415 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
1416 event_update_signal_fd(s->event);
1417 }
1418
1419 break;
1420
6203e07a 1421 case SOURCE_EXIT:
305f78bf 1422 s->enabled = m;
6203e07a 1423 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1424 break;
1425
1426 case SOURCE_DEFER:
6e9feda3 1427 case SOURCE_POST:
baf76283 1428 s->enabled = m;
fd38203a 1429 break;
9d3e3aa5 1430
6a0f1f6d 1431 default:
9d3e3aa5 1432 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
1433 }
1434
1435 } else {
1436 switch (s->type) {
1437
1438 case SOURCE_IO:
1439 r = source_io_register(s, m, s->io.events);
1440 if (r < 0)
1441 return r;
1442
baf76283 1443 s->enabled = m;
fd38203a
LP
1444 break;
1445
6a0f1f6d
LP
1446 case SOURCE_TIME_REALTIME:
1447 case SOURCE_TIME_MONOTONIC:
1448 case SOURCE_TIME_REALTIME_ALARM:
1449 case SOURCE_TIME_BOOTTIME_ALARM: {
1450 struct clock_data *d;
fd38203a 1451
baf76283 1452 s->enabled = m;
6a0f1f6d
LP
1453 d = event_get_clock_data(s->event, s->type);
1454 assert(d);
1455
1456 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1457 prioq_reshuffle(d->latest, s, &s->time.latest_index);
fd38203a 1458 break;
6a0f1f6d 1459 }
fd38203a
LP
1460
1461 case SOURCE_SIGNAL:
baf76283 1462 s->enabled = m;
fd38203a 1463
baf76283 1464 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1465 assert_se(sigaddset(&s->event->sigset, s->signal.sig) == 0);
1466 event_update_signal_fd(s->event);
1467 }
1468 break;
1469
1470 case SOURCE_CHILD:
baf76283
LP
1471 if (s->enabled == SD_EVENT_OFF) {
1472 s->event->n_enabled_child_sources++;
fd38203a
LP
1473
1474 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1475 assert_se(sigaddset(&s->event->sigset, SIGCHLD) == 0);
1476 event_update_signal_fd(s->event);
1477 }
1478 }
7a0d4a3d
DH
1479
1480 s->enabled = m;
fd38203a
LP
1481 break;
1482
6203e07a 1483 case SOURCE_EXIT:
305f78bf 1484 s->enabled = m;
6203e07a 1485 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1486 break;
1487
1488 case SOURCE_DEFER:
6e9feda3 1489 case SOURCE_POST:
baf76283 1490 s->enabled = m;
fd38203a 1491 break;
9d3e3aa5 1492
6a0f1f6d 1493 default:
9d3e3aa5 1494 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
1495 }
1496 }
1497
1498 if (s->pending)
1499 prioq_reshuffle(s->event->pending, s, &s->pending_index);
1500
1501 if (s->prepare)
1502 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
1503
1504 return 0;
1505}
1506
f7262a9f 1507_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1508 assert_return(s, -EINVAL);
1509 assert_return(usec, -EINVAL);
6a0f1f6d 1510 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
305f78bf 1511 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1512
1513 *usec = s->time.next;
1514 return 0;
1515}
1516
f7262a9f 1517_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
6a0f1f6d
LP
1518 struct clock_data *d;
1519
305f78bf
LP
1520 assert_return(s, -EINVAL);
1521 assert_return(usec != (uint64_t) -1, -EINVAL);
6a0f1f6d 1522 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
da7e457c 1523 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1524 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1525
fd38203a 1526 s->time.next = usec;
2576a19e 1527
0cc1125a 1528 source_set_pending(s, false);
fd38203a 1529
6a0f1f6d
LP
1530 d = event_get_clock_data(s->event, s->type);
1531 assert(d);
1532
1533 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1534 prioq_reshuffle(d->latest, s, &s->time.latest_index);
fd38203a
LP
1535
1536 return 0;
1537}
1538
f7262a9f 1539_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1540 assert_return(s, -EINVAL);
1541 assert_return(usec, -EINVAL);
6a0f1f6d 1542 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
305f78bf
LP
1543 assert_return(!event_pid_changed(s->event), -ECHILD);
1544
1545 *usec = s->time.accuracy;
1546 return 0;
1547}
1548
f7262a9f 1549_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
6a0f1f6d
LP
1550 struct clock_data *d;
1551
305f78bf
LP
1552 assert_return(s, -EINVAL);
1553 assert_return(usec != (uint64_t) -1, -EINVAL);
6a0f1f6d 1554 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
da7e457c 1555 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1556 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef
LP
1557
1558 if (usec == 0)
1559 usec = DEFAULT_ACCURACY_USEC;
1560
eaa3cbef
LP
1561 s->time.accuracy = usec;
1562
2576a19e
LP
1563 source_set_pending(s, false);
1564
6a0f1f6d
LP
1565 d = event_get_clock_data(s->event, s->type);
1566 assert(d);
1567
1568 prioq_reshuffle(d->latest, s, &s->time.latest_index);
1569
1570 return 0;
1571}
1572
1573_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) {
1574 assert_return(s, -EINVAL);
1575 assert_return(clock, -EINVAL);
1576 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
1577 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef 1578
6a0f1f6d 1579 *clock = event_source_type_to_clock(s->type);
eaa3cbef
LP
1580 return 0;
1581}
1582
f7262a9f 1583_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
4bee8012
LP
1584 assert_return(s, -EINVAL);
1585 assert_return(pid, -EINVAL);
1586 assert_return(s->type == SOURCE_CHILD, -EDOM);
1587 assert_return(!event_pid_changed(s->event), -ECHILD);
1588
1589 *pid = s->child.pid;
1590 return 0;
1591}
1592
718db961 1593_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
fd38203a
LP
1594 int r;
1595
da7e457c 1596 assert_return(s, -EINVAL);
6203e07a 1597 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c
LP
1598 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
1599 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1600
1601 if (s->prepare == callback)
1602 return 0;
1603
1604 if (callback && s->prepare) {
1605 s->prepare = callback;
1606 return 0;
1607 }
1608
1609 r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare);
1610 if (r < 0)
1611 return r;
1612
1613 s->prepare = callback;
1614
1615 if (callback) {
1616 r = prioq_put(s->event->prepare, s, &s->prepare_index);
1617 if (r < 0)
1618 return r;
1619 } else
1620 prioq_remove(s->event->prepare, s, &s->prepare_index);
1621
1622 return 0;
1623}
1624
f7262a9f 1625_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
da7e457c 1626 assert_return(s, NULL);
fd38203a
LP
1627
1628 return s->userdata;
1629}
1630
8f726607
LP
1631_public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) {
1632 void *ret;
1633
1634 assert_return(s, NULL);
1635
1636 ret = s->userdata;
1637 s->userdata = userdata;
1638
1639 return ret;
1640}
1641
c2ba3ad6
LP
1642static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
1643 usec_t c;
1644 assert(e);
1645 assert(a <= b);
1646
1647 if (a <= 0)
1648 return 0;
1649
1650 if (b <= a + 1)
1651 return a;
1652
52444dc4
LP
1653 initialize_perturb(e);
1654
c2ba3ad6
LP
1655 /*
1656 Find a good time to wake up again between times a and b. We
1657 have two goals here:
1658
1659 a) We want to wake up as seldom as possible, hence prefer
1660 later times over earlier times.
1661
1662 b) But if we have to wake up, then let's make sure to
1663 dispatch as much as possible on the entire system.
1664
1665 We implement this by waking up everywhere at the same time
850516e0 1666 within any given minute if we can, synchronised via the
c2ba3ad6 1667 perturbation value determined from the boot ID. If we can't,
ba276c81
LP
1668 then we try to find the same spot in every 10s, then 1s and
1669 then 250ms step. Otherwise, we pick the last possible time
1670 to wake up.
c2ba3ad6
LP
1671 */
1672
850516e0
LP
1673 c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb;
1674 if (c >= b) {
1675 if (_unlikely_(c < USEC_PER_MINUTE))
1676 return b;
1677
1678 c -= USEC_PER_MINUTE;
1679 }
1680
ba276c81
LP
1681 if (c >= a)
1682 return c;
1683
1684 c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10));
1685 if (c >= b) {
1686 if (_unlikely_(c < USEC_PER_SEC*10))
1687 return b;
1688
1689 c -= USEC_PER_SEC*10;
1690 }
1691
850516e0
LP
1692 if (c >= a)
1693 return c;
1694
1695 c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC);
c2ba3ad6
LP
1696 if (c >= b) {
1697 if (_unlikely_(c < USEC_PER_SEC))
1698 return b;
1699
1700 c -= USEC_PER_SEC;
1701 }
1702
1703 if (c >= a)
1704 return c;
1705
1706 c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250));
1707 if (c >= b) {
1708 if (_unlikely_(c < USEC_PER_MSEC*250))
1709 return b;
1710
1711 c -= USEC_PER_MSEC*250;
1712 }
1713
1714 if (c >= a)
1715 return c;
1716
1717 return b;
1718}
1719
fd38203a
LP
1720static int event_arm_timer(
1721 sd_event *e,
6a0f1f6d 1722 struct clock_data *d) {
fd38203a
LP
1723
1724 struct itimerspec its = {};
c2ba3ad6
LP
1725 sd_event_source *a, *b;
1726 usec_t t;
fd38203a
LP
1727 int r;
1728
cde93897 1729 assert(e);
6a0f1f6d 1730 assert(d);
fd38203a 1731
6a0f1f6d 1732 a = prioq_peek(d->earliest);
72aedc1e
LP
1733 if (!a || a->enabled == SD_EVENT_OFF) {
1734
6a0f1f6d 1735 if (d->fd < 0)
c57b5ca3
LP
1736 return 0;
1737
6a0f1f6d 1738 if (d->next == (usec_t) -1)
72aedc1e
LP
1739 return 0;
1740
1741 /* disarm */
6a0f1f6d 1742 r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
72aedc1e
LP
1743 if (r < 0)
1744 return r;
1745
6a0f1f6d 1746 d->next = (usec_t) -1;
fd38203a 1747 return 0;
72aedc1e 1748 }
fd38203a 1749
6a0f1f6d 1750 b = prioq_peek(d->latest);
baf76283 1751 assert_se(b && b->enabled != SD_EVENT_OFF);
c2ba3ad6
LP
1752
1753 t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
6a0f1f6d 1754 if (d->next == t)
fd38203a
LP
1755 return 0;
1756
6a0f1f6d 1757 assert_se(d->fd >= 0);
fd38203a 1758
c2ba3ad6 1759 if (t == 0) {
fd38203a
LP
1760 /* We don' want to disarm here, just mean some time looooong ago. */
1761 its.it_value.tv_sec = 0;
1762 its.it_value.tv_nsec = 1;
1763 } else
c2ba3ad6 1764 timespec_store(&its.it_value, t);
fd38203a 1765
6a0f1f6d 1766 r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
fd38203a 1767 if (r < 0)
cde93897 1768 return -errno;
fd38203a 1769
6a0f1f6d 1770 d->next = t;
fd38203a
LP
1771 return 0;
1772}
1773
9a800b56 1774static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) {
fd38203a
LP
1775 assert(e);
1776 assert(s);
1777 assert(s->type == SOURCE_IO);
1778
9a800b56
LP
1779 /* If the event source was already pending, we just OR in the
1780 * new revents, otherwise we reset the value. The ORing is
1781 * necessary to handle EPOLLONESHOT events properly where
1782 * readability might happen independently of writability, and
1783 * we need to keep track of both */
1784
1785 if (s->pending)
1786 s->io.revents |= revents;
1787 else
1788 s->io.revents = revents;
fd38203a 1789
fd38203a
LP
1790 return source_set_pending(s, true);
1791}
1792
72aedc1e 1793static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
fd38203a
LP
1794 uint64_t x;
1795 ssize_t ss;
1796
1797 assert(e);
da7e457c 1798 assert(fd >= 0);
72aedc1e 1799
305f78bf 1800 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1801
1802 ss = read(fd, &x, sizeof(x));
1803 if (ss < 0) {
1804 if (errno == EAGAIN || errno == EINTR)
1805 return 0;
1806
1807 return -errno;
1808 }
1809
8d35dae7 1810 if (_unlikely_(ss != sizeof(x)))
fd38203a
LP
1811 return -EIO;
1812
cde93897
LP
1813 if (next)
1814 *next = (usec_t) -1;
72aedc1e 1815
fd38203a
LP
1816 return 0;
1817}
1818
305f78bf
LP
1819static int process_timer(
1820 sd_event *e,
1821 usec_t n,
6a0f1f6d 1822 struct clock_data *d) {
305f78bf 1823
fd38203a
LP
1824 sd_event_source *s;
1825 int r;
1826
1827 assert(e);
6a0f1f6d 1828 assert(d);
fd38203a
LP
1829
1830 for (;;) {
6a0f1f6d 1831 s = prioq_peek(d->earliest);
fd38203a
LP
1832 if (!s ||
1833 s->time.next > n ||
baf76283 1834 s->enabled == SD_EVENT_OFF ||
fd38203a
LP
1835 s->pending)
1836 break;
1837
1838 r = source_set_pending(s, true);
1839 if (r < 0)
1840 return r;
1841
6a0f1f6d
LP
1842 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1843 prioq_reshuffle(d->latest, s, &s->time.latest_index);
fd38203a
LP
1844 }
1845
1846 return 0;
1847}
1848
1849static int process_child(sd_event *e) {
1850 sd_event_source *s;
1851 Iterator i;
1852 int r;
1853
1854 assert(e);
1855
c2ba3ad6
LP
1856 e->need_process_child = false;
1857
fd38203a
LP
1858 /*
1859 So, this is ugly. We iteratively invoke waitid() with P_PID
1860 + WNOHANG for each PID we wait for, instead of using
1861 P_ALL. This is because we only want to get child
1862 information of very specific child processes, and not all
1863 of them. We might not have processed the SIGCHLD even of a
1864 previous invocation and we don't want to maintain a
1865 unbounded *per-child* event queue, hence we really don't
1866 want anything flushed out of the kernel's queue that we
1867 don't care about. Since this is O(n) this means that if you
1868 have a lot of processes you probably want to handle SIGCHLD
1869 yourself.
08cd1552
LP
1870
1871 We do not reap the children here (by using WNOWAIT), this
1872 is only done after the event source is dispatched so that
1873 the callback still sees the process as a zombie.
fd38203a
LP
1874 */
1875
1876 HASHMAP_FOREACH(s, e->child_sources, i) {
1877 assert(s->type == SOURCE_CHILD);
1878
1879 if (s->pending)
1880 continue;
1881
baf76283 1882 if (s->enabled == SD_EVENT_OFF)
fd38203a
LP
1883 continue;
1884
1885 zero(s->child.siginfo);
08cd1552
LP
1886 r = waitid(P_PID, s->child.pid, &s->child.siginfo,
1887 WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options);
fd38203a
LP
1888 if (r < 0)
1889 return -errno;
1890
1891 if (s->child.siginfo.si_pid != 0) {
08cd1552
LP
1892 bool zombie =
1893 s->child.siginfo.si_code == CLD_EXITED ||
1894 s->child.siginfo.si_code == CLD_KILLED ||
1895 s->child.siginfo.si_code == CLD_DUMPED;
1896
1897 if (!zombie && (s->child.options & WEXITED)) {
1898 /* If the child isn't dead then let's
1899 * immediately remove the state change
1900 * from the queue, since there's no
1901 * benefit in leaving it queued */
1902
1903 assert(s->child.options & (WSTOPPED|WCONTINUED));
1904 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED)));
1905 }
1906
fd38203a
LP
1907 r = source_set_pending(s, true);
1908 if (r < 0)
1909 return r;
1910 }
1911 }
1912
fd38203a
LP
1913 return 0;
1914}
1915
1916static int process_signal(sd_event *e, uint32_t events) {
fd38203a 1917 bool read_one = false;
fd38203a
LP
1918 int r;
1919
da7e457c 1920 assert(e);
0eb2e0e3
ZJS
1921 assert(e->signal_sources);
1922
305f78bf 1923 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1924
1925 for (;;) {
0eb2e0e3
ZJS
1926 struct signalfd_siginfo si;
1927 ssize_t ss;
fd38203a
LP
1928 sd_event_source *s;
1929
1930 ss = read(e->signal_fd, &si, sizeof(si));
1931 if (ss < 0) {
1932 if (errno == EAGAIN || errno == EINTR)
1933 return read_one;
1934
1935 return -errno;
1936 }
1937
8d35dae7 1938 if (_unlikely_(ss != sizeof(si)))
fd38203a
LP
1939 return -EIO;
1940
1941 read_one = true;
1942
0eb2e0e3 1943 s = e->signal_sources[si.ssi_signo];
fd38203a
LP
1944 if (si.ssi_signo == SIGCHLD) {
1945 r = process_child(e);
1946 if (r < 0)
1947 return r;
0eb2e0e3 1948 if (r > 0 || !s)
fd38203a 1949 continue;
0eb2e0e3 1950 } else
fd38203a
LP
1951 if (!s)
1952 return -EIO;
fd38203a
LP
1953
1954 s->signal.siginfo = si;
1955 r = source_set_pending(s, true);
1956 if (r < 0)
1957 return r;
1958 }
fd38203a
LP
1959}
1960
1961static int source_dispatch(sd_event_source *s) {
fe8245eb 1962 int r = 0;
fd38203a
LP
1963
1964 assert(s);
6203e07a 1965 assert(s->pending || s->type == SOURCE_EXIT);
fd38203a 1966
6203e07a 1967 if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) {
da7e457c
LP
1968 r = source_set_pending(s, false);
1969 if (r < 0)
1970 return r;
1971 }
fd38203a 1972
6e9feda3
LP
1973 if (s->type != SOURCE_POST) {
1974 sd_event_source *z;
1975 Iterator i;
1976
1977 /* If we execute a non-post source, let's mark all
1978 * post sources as pending */
1979
1980 SET_FOREACH(z, s->event->post_sources, i) {
1981 if (z->enabled == SD_EVENT_OFF)
1982 continue;
1983
1984 r = source_set_pending(z, true);
1985 if (r < 0)
1986 return r;
1987 }
1988 }
1989
baf76283
LP
1990 if (s->enabled == SD_EVENT_ONESHOT) {
1991 r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
1992 if (r < 0)
1993 return r;
1994 }
1995
12179984 1996 s->dispatching = true;
b7484e2a 1997
fd38203a
LP
1998 switch (s->type) {
1999
2000 case SOURCE_IO:
2001 r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata);
2002 break;
2003
6a0f1f6d
LP
2004 case SOURCE_TIME_REALTIME:
2005 case SOURCE_TIME_MONOTONIC:
2006 case SOURCE_TIME_REALTIME_ALARM:
2007 case SOURCE_TIME_BOOTTIME_ALARM:
fd38203a
LP
2008 r = s->time.callback(s, s->time.next, s->userdata);
2009 break;
2010
2011 case SOURCE_SIGNAL:
2012 r = s->signal.callback(s, &s->signal.siginfo, s->userdata);
2013 break;
2014
08cd1552
LP
2015 case SOURCE_CHILD: {
2016 bool zombie;
2017
2018 zombie = s->child.siginfo.si_code == CLD_EXITED ||
2019 s->child.siginfo.si_code == CLD_KILLED ||
2020 s->child.siginfo.si_code == CLD_DUMPED;
2021
fd38203a 2022 r = s->child.callback(s, &s->child.siginfo, s->userdata);
08cd1552
LP
2023
2024 /* Now, reap the PID for good. */
2025 if (zombie)
2026 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
2027
fd38203a 2028 break;
08cd1552 2029 }
fd38203a
LP
2030
2031 case SOURCE_DEFER:
2032 r = s->defer.callback(s, s->userdata);
2033 break;
da7e457c 2034
6e9feda3
LP
2035 case SOURCE_POST:
2036 r = s->post.callback(s, s->userdata);
2037 break;
2038
6203e07a
LP
2039 case SOURCE_EXIT:
2040 r = s->exit.callback(s, s->userdata);
da7e457c 2041 break;
9d3e3aa5
LP
2042
2043 case SOURCE_WATCHDOG:
a71fe8b8 2044 case _SOURCE_EVENT_SOURCE_TYPE_MAX:
9f2a50a3 2045 case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
9d3e3aa5 2046 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
2047 }
2048
12179984
LP
2049 s->dispatching = false;
2050
2051 if (r < 0)
6203e07a 2052 log_debug("Event source %p returned error, disabling: %s", s, strerror(-r));
12179984
LP
2053
2054 if (s->n_ref == 0)
2055 source_free(s);
2056 else if (r < 0)
6203e07a 2057 sd_event_source_set_enabled(s, SD_EVENT_OFF);
b7484e2a 2058
6203e07a 2059 return 1;
fd38203a
LP
2060}
2061
2062static int event_prepare(sd_event *e) {
2063 int r;
2064
2065 assert(e);
2066
2067 for (;;) {
2068 sd_event_source *s;
2069
2070 s = prioq_peek(e->prepare);
baf76283 2071 if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF)
fd38203a
LP
2072 break;
2073
2074 s->prepare_iteration = e->iteration;
2075 r = prioq_reshuffle(e->prepare, s, &s->prepare_index);
2076 if (r < 0)
2077 return r;
2078
2079 assert(s->prepare);
12179984
LP
2080
2081 s->dispatching = true;
fd38203a 2082 r = s->prepare(s, s->userdata);
12179984
LP
2083 s->dispatching = false;
2084
fd38203a 2085 if (r < 0)
12179984 2086 log_debug("Prepare callback of event source %p returned error, disabling: %s", s, strerror(-r));
fd38203a 2087
12179984
LP
2088 if (s->n_ref == 0)
2089 source_free(s);
2090 else if (r < 0)
2091 sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
2092 }
2093
2094 return 0;
2095}
2096
6203e07a 2097static int dispatch_exit(sd_event *e) {
da7e457c
LP
2098 sd_event_source *p;
2099 int r;
2100
2101 assert(e);
2102
6203e07a 2103 p = prioq_peek(e->exit);
baf76283 2104 if (!p || p->enabled == SD_EVENT_OFF) {
da7e457c
LP
2105 e->state = SD_EVENT_FINISHED;
2106 return 0;
2107 }
2108
2109 sd_event_ref(e);
2110 e->iteration++;
6203e07a 2111 e->state = SD_EVENT_EXITING;
da7e457c
LP
2112
2113 r = source_dispatch(p);
2114
2115 e->state = SD_EVENT_PASSIVE;
2116 sd_event_unref(e);
2117
2118 return r;
2119}
2120
c2ba3ad6
LP
2121static sd_event_source* event_next_pending(sd_event *e) {
2122 sd_event_source *p;
2123
da7e457c
LP
2124 assert(e);
2125
c2ba3ad6
LP
2126 p = prioq_peek(e->pending);
2127 if (!p)
2128 return NULL;
2129
baf76283 2130 if (p->enabled == SD_EVENT_OFF)
c2ba3ad6
LP
2131 return NULL;
2132
2133 return p;
2134}
2135
cde93897
LP
2136static int arm_watchdog(sd_event *e) {
2137 struct itimerspec its = {};
2138 usec_t t;
2139 int r;
2140
2141 assert(e);
2142 assert(e->watchdog_fd >= 0);
2143
2144 t = sleep_between(e,
2145 e->watchdog_last + (e->watchdog_period / 2),
2146 e->watchdog_last + (e->watchdog_period * 3 / 4));
2147
2148 timespec_store(&its.it_value, t);
2149
75145780
LP
2150 /* Make sure we never set the watchdog to 0, which tells the
2151 * kernel to disable it. */
2152 if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
2153 its.it_value.tv_nsec = 1;
2154
cde93897
LP
2155 r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL);
2156 if (r < 0)
2157 return -errno;
2158
2159 return 0;
2160}
2161
2162static int process_watchdog(sd_event *e) {
2163 assert(e);
2164
2165 if (!e->watchdog)
2166 return 0;
2167
2168 /* Don't notify watchdog too often */
2169 if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic)
2170 return 0;
2171
2172 sd_notify(false, "WATCHDOG=1");
2173 e->watchdog_last = e->timestamp.monotonic;
2174
2175 return arm_watchdog(e);
2176}
2177
f7262a9f 2178_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
15b38f93
LP
2179 struct epoll_event *ev_queue;
2180 unsigned ev_queue_max;
fd38203a 2181 sd_event_source *p;
305f78bf 2182 int r, i, m;
eec6022c 2183 bool timedout;
fd38203a 2184
da7e457c
LP
2185 assert_return(e, -EINVAL);
2186 assert_return(!event_pid_changed(e), -ECHILD);
2187 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2188 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
2189
6203e07a
LP
2190 if (e->exit_requested)
2191 return dispatch_exit(e);
fd38203a 2192
da7e457c 2193 sd_event_ref(e);
fd38203a 2194 e->iteration++;
da7e457c 2195 e->state = SD_EVENT_RUNNING;
fd38203a
LP
2196
2197 r = event_prepare(e);
2198 if (r < 0)
da7e457c 2199 goto finish;
fd38203a 2200
6a0f1f6d
LP
2201 r = event_arm_timer(e, &e->realtime);
2202 if (r < 0)
2203 goto finish;
2204
2205 r = event_arm_timer(e, &e->monotonic);
2206 if (r < 0)
2207 goto finish;
2208
2209 r = event_arm_timer(e, &e->realtime_alarm);
1b5995b0
LP
2210 if (r < 0)
2211 goto finish;
fd38203a 2212
6a0f1f6d 2213 r = event_arm_timer(e, &e->boottime_alarm);
1b5995b0
LP
2214 if (r < 0)
2215 goto finish;
fd38203a 2216
1b5995b0
LP
2217 if (event_next_pending(e) || e->need_process_child)
2218 timeout = 0;
6a0f1f6d 2219
15b38f93
LP
2220 ev_queue_max = CLAMP(e->n_sources, 1U, EPOLL_QUEUE_MAX);
2221 ev_queue = newa(struct epoll_event, ev_queue_max);
fd38203a 2222
15b38f93 2223 m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
c2ba3ad6 2224 timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
da7e457c 2225 if (m < 0) {
ff003106 2226 r = errno == EAGAIN || errno == EINTR ? 1 : -errno;
da7e457c
LP
2227 goto finish;
2228 }
fd38203a 2229
eec6022c
LP
2230 timedout = m == 0;
2231
46e8c825 2232 dual_timestamp_get(&e->timestamp);
6a0f1f6d 2233 e->timestamp_boottime = now(CLOCK_BOOTTIME);
fd38203a
LP
2234
2235 for (i = 0; i < m; i++) {
2236
6a0f1f6d
LP
2237 if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_REALTIME))
2238 r = flush_timer(e, e->realtime.fd, ev_queue[i].events, &e->realtime.next);
2239 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_MONOTONIC))
2240 r = flush_timer(e, e->monotonic.fd, ev_queue[i].events, &e->monotonic.next);
2241 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_REALTIME_ALARM))
2242 r = flush_timer(e, e->realtime_alarm.fd, ev_queue[i].events, &e->realtime_alarm.next);
2243 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_BOOTTIME_ALARM))
2244 r = flush_timer(e, e->boottime_alarm.fd, ev_queue[i].events, &e->boottime_alarm.next);
fd38203a
LP
2245 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_SIGNAL))
2246 r = process_signal(e, ev_queue[i].events);
79e16ce3 2247 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG))
cde93897 2248 r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL);
fd38203a
LP
2249 else
2250 r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
2251
2252 if (r < 0)
da7e457c 2253 goto finish;
fd38203a
LP
2254 }
2255
cde93897
LP
2256 r = process_watchdog(e);
2257 if (r < 0)
2258 goto finish;
2259
6a0f1f6d
LP
2260 r = process_timer(e, e->timestamp.realtime, &e->realtime);
2261 if (r < 0)
2262 goto finish;
2263
2264 r = process_timer(e, e->timestamp.monotonic, &e->monotonic);
2265 if (r < 0)
2266 goto finish;
2267
2268 r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm);
fd38203a 2269 if (r < 0)
da7e457c 2270 goto finish;
fd38203a 2271
6a0f1f6d 2272 r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm);
fd38203a 2273 if (r < 0)
da7e457c 2274 goto finish;
fd38203a 2275
c2ba3ad6 2276 if (e->need_process_child) {
fd38203a
LP
2277 r = process_child(e);
2278 if (r < 0)
da7e457c 2279 goto finish;
fd38203a
LP
2280 }
2281
c2ba3ad6 2282 p = event_next_pending(e);
da7e457c 2283 if (!p) {
eec6022c 2284 r = !timedout;
da7e457c
LP
2285 goto finish;
2286 }
2287
2288 r = source_dispatch(p);
fd38203a 2289
da7e457c
LP
2290finish:
2291 e->state = SD_EVENT_PASSIVE;
2292 sd_event_unref(e);
2293
2294 return r;
fd38203a
LP
2295}
2296
f7262a9f 2297_public_ int sd_event_loop(sd_event *e) {
fd38203a
LP
2298 int r;
2299
da7e457c
LP
2300 assert_return(e, -EINVAL);
2301 assert_return(!event_pid_changed(e), -ECHILD);
2302 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
2303
2304 sd_event_ref(e);
fd38203a 2305
da7e457c 2306 while (e->state != SD_EVENT_FINISHED) {
fd38203a
LP
2307 r = sd_event_run(e, (uint64_t) -1);
2308 if (r < 0)
da7e457c 2309 goto finish;
fd38203a
LP
2310 }
2311
6203e07a 2312 r = e->exit_code;
da7e457c
LP
2313
2314finish:
2315 sd_event_unref(e);
2316 return r;
fd38203a
LP
2317}
2318
f7262a9f 2319_public_ int sd_event_get_state(sd_event *e) {
da7e457c
LP
2320 assert_return(e, -EINVAL);
2321 assert_return(!event_pid_changed(e), -ECHILD);
2322
2323 return e->state;
2324}
2325
6203e07a 2326_public_ int sd_event_get_exit_code(sd_event *e, int *code) {
da7e457c 2327 assert_return(e, -EINVAL);
6203e07a 2328 assert_return(code, -EINVAL);
da7e457c 2329 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 2330
6203e07a
LP
2331 if (!e->exit_requested)
2332 return -ENODATA;
2333
2334 *code = e->exit_code;
2335 return 0;
fd38203a
LP
2336}
2337
6203e07a 2338_public_ int sd_event_exit(sd_event *e, int code) {
da7e457c
LP
2339 assert_return(e, -EINVAL);
2340 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2341 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 2342
6203e07a
LP
2343 e->exit_requested = true;
2344 e->exit_code = code;
2345
fd38203a
LP
2346 return 0;
2347}
46e8c825 2348
6a0f1f6d 2349_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
46e8c825
LP
2350 assert_return(e, -EINVAL);
2351 assert_return(usec, -EINVAL);
46e8c825
LP
2352 assert_return(!event_pid_changed(e), -ECHILD);
2353
6a0f1f6d
LP
2354 /* If we haven't run yet, just get the actual time */
2355 if (!dual_timestamp_is_set(&e->timestamp))
2356 return -ENODATA;
46e8c825 2357
6a0f1f6d
LP
2358 switch (clock) {
2359
2360 case CLOCK_REALTIME:
2361 case CLOCK_REALTIME_ALARM:
2362 *usec = e->timestamp.realtime;
2363 break;
2364
2365 case CLOCK_MONOTONIC:
2366 *usec = e->timestamp.monotonic;
2367 break;
2368
2369 case CLOCK_BOOTTIME_ALARM:
2370 *usec = e->timestamp_boottime;
2371 break;
2372 }
46e8c825 2373
46e8c825
LP
2374 return 0;
2375}
afc6adb5
LP
2376
2377_public_ int sd_event_default(sd_event **ret) {
2378
ec202eae 2379 static thread_local sd_event *default_event = NULL;
39883f62 2380 sd_event *e = NULL;
afc6adb5
LP
2381 int r;
2382
2383 if (!ret)
2384 return !!default_event;
2385
2386 if (default_event) {
2387 *ret = sd_event_ref(default_event);
2388 return 0;
2389 }
2390
2391 r = sd_event_new(&e);
2392 if (r < 0)
2393 return r;
2394
2395 e->default_event_ptr = &default_event;
2396 e->tid = gettid();
2397 default_event = e;
2398
2399 *ret = e;
2400 return 1;
2401}
2402
2403_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
2404 assert_return(e, -EINVAL);
2405 assert_return(tid, -EINVAL);
76b54375 2406 assert_return(!event_pid_changed(e), -ECHILD);
afc6adb5 2407
76b54375
LP
2408 if (e->tid != 0) {
2409 *tid = e->tid;
2410 return 0;
2411 }
2412
2413 return -ENXIO;
afc6adb5 2414}
cde93897
LP
2415
2416_public_ int sd_event_set_watchdog(sd_event *e, int b) {
2417 int r;
2418
2419 assert_return(e, -EINVAL);
8f726607 2420 assert_return(!event_pid_changed(e), -ECHILD);
cde93897
LP
2421
2422 if (e->watchdog == !!b)
2423 return e->watchdog;
2424
2425 if (b) {
2426 struct epoll_event ev = {};
cde93897 2427
09812eb7
LP
2428 r = sd_watchdog_enabled(false, &e->watchdog_period);
2429 if (r <= 0)
cde93897 2430 return r;
cde93897
LP
2431
2432 /* Issue first ping immediately */
2433 sd_notify(false, "WATCHDOG=1");
2434 e->watchdog_last = now(CLOCK_MONOTONIC);
2435
2436 e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
2437 if (e->watchdog_fd < 0)
2438 return -errno;
2439
2440 r = arm_watchdog(e);
2441 if (r < 0)
2442 goto fail;
2443
2444 ev.events = EPOLLIN;
2445 ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
2446
2447 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
2448 if (r < 0) {
2449 r = -errno;
2450 goto fail;
2451 }
2452
2453 } else {
2454 if (e->watchdog_fd >= 0) {
2455 epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL);
03e334a1 2456 e->watchdog_fd = safe_close(e->watchdog_fd);
cde93897
LP
2457 }
2458 }
2459
2460 e->watchdog = !!b;
2461 return e->watchdog;
2462
2463fail:
03e334a1 2464 e->watchdog_fd = safe_close(e->watchdog_fd);
cde93897
LP
2465 return r;
2466}
8f726607
LP
2467
2468_public_ int sd_event_get_watchdog(sd_event *e) {
2469 assert_return(e, -EINVAL);
2470 assert_return(!event_pid_changed(e), -ECHILD);
2471
2472 return e->watchdog;
2473}