]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-event.c
bus: make sure an additional ref to a busevent source doesn't cause the event source...
[thirdparty/systemd.git] / src / libsystemd-bus / 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>
25
afc6adb5 26#include "sd-id128.h"
fd38203a 27#include "macro.h"
fd38203a
LP
28#include "prioq.h"
29#include "hashmap.h"
30#include "util.h"
31#include "time-util.h"
afc6adb5 32#include "missing.h"
fd38203a
LP
33
34#include "sd-event.h"
35
36#define EPOLL_QUEUE_MAX 64
c2ba3ad6 37#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
fd38203a
LP
38
39typedef enum EventSourceType {
40 SOURCE_IO,
41 SOURCE_MONOTONIC,
42 SOURCE_REALTIME,
43 SOURCE_SIGNAL,
44 SOURCE_CHILD,
da7e457c
LP
45 SOURCE_DEFER,
46 SOURCE_QUIT
fd38203a
LP
47} EventSourceType;
48
49struct sd_event_source {
da7e457c 50 unsigned n_ref;
fd38203a
LP
51
52 sd_event *event;
53 void *userdata;
718db961 54 sd_event_handler_t prepare;
fd38203a
LP
55
56 EventSourceType type:4;
baf76283 57 int enabled:3;
fd38203a
LP
58 bool pending:1;
59
60 int priority;
61 unsigned pending_index;
62 unsigned prepare_index;
63 unsigned pending_iteration;
64 unsigned prepare_iteration;
65
66 union {
67 struct {
718db961 68 sd_event_io_handler_t callback;
fd38203a
LP
69 int fd;
70 uint32_t events;
71 uint32_t revents;
72 bool registered:1;
73 } io;
74 struct {
718db961 75 sd_event_time_handler_t callback;
c2ba3ad6
LP
76 usec_t next, accuracy;
77 unsigned earliest_index;
78 unsigned latest_index;
fd38203a
LP
79 } time;
80 struct {
718db961 81 sd_event_signal_handler_t callback;
fd38203a
LP
82 struct signalfd_siginfo siginfo;
83 int sig;
84 } signal;
85 struct {
718db961 86 sd_event_child_handler_t callback;
fd38203a
LP
87 siginfo_t siginfo;
88 pid_t pid;
89 int options;
90 } child;
91 struct {
718db961 92 sd_event_handler_t callback;
fd38203a 93 } defer;
da7e457c 94 struct {
718db961 95 sd_event_handler_t callback;
da7e457c
LP
96 unsigned prioq_index;
97 } quit;
fd38203a
LP
98 };
99};
100
101struct sd_event {
da7e457c 102 unsigned n_ref;
fd38203a
LP
103
104 int epoll_fd;
105 int signal_fd;
106 int realtime_fd;
107 int monotonic_fd;
108
109 Prioq *pending;
110 Prioq *prepare;
c2ba3ad6
LP
111
112 /* For both clocks we maintain two priority queues each, one
113 * ordered for the earliest times the events may be
114 * dispatched, and one ordered by the latest times they must
115 * have been dispatched. The range between the top entries in
116 * the two prioqs is the time window we can freely schedule
117 * wakeups in */
118 Prioq *monotonic_earliest;
119 Prioq *monotonic_latest;
120 Prioq *realtime_earliest;
121 Prioq *realtime_latest;
fd38203a 122
da7e457c
LP
123 usec_t realtime_next, monotonic_next;
124 usec_t perturb;
125
fd38203a
LP
126 sigset_t sigset;
127 sd_event_source **signal_sources;
128
129 Hashmap *child_sources;
baf76283 130 unsigned n_enabled_child_sources;
fd38203a 131
da7e457c 132 Prioq *quit;
fd38203a 133
da7e457c 134 pid_t original_pid;
c2ba3ad6 135
da7e457c 136 unsigned iteration;
46e8c825 137 dual_timestamp timestamp;
da7e457c 138 int state;
eaa3cbef 139
da7e457c
LP
140 bool quit_requested:1;
141 bool need_process_child:1;
afc6adb5
LP
142
143 pid_t tid;
144 sd_event **default_event_ptr;
fd38203a
LP
145};
146
147static int pending_prioq_compare(const void *a, const void *b) {
148 const sd_event_source *x = a, *y = b;
149
150 assert(x->pending);
151 assert(y->pending);
152
baf76283
LP
153 /* Enabled ones first */
154 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 155 return -1;
baf76283 156 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
157 return 1;
158
159 /* Lower priority values first */
160 if (x->priority < y->priority)
161 return -1;
162 if (x->priority > y->priority)
163 return 1;
164
165 /* Older entries first */
166 if (x->pending_iteration < y->pending_iteration)
167 return -1;
168 if (x->pending_iteration > y->pending_iteration)
169 return 1;
170
171 /* Stability for the rest */
172 if (x < y)
173 return -1;
dfcd88f6 174 if (x > y)
fd38203a
LP
175 return 1;
176
177 return 0;
178}
179
180static int prepare_prioq_compare(const void *a, const void *b) {
181 const sd_event_source *x = a, *y = b;
182
183 assert(x->prepare);
184 assert(y->prepare);
185
186 /* Move most recently prepared ones last, so that we can stop
187 * preparing as soon as we hit one that has already been
188 * prepared in the current iteration */
189 if (x->prepare_iteration < y->prepare_iteration)
190 return -1;
191 if (x->prepare_iteration > y->prepare_iteration)
192 return 1;
193
baf76283
LP
194 /* Enabled ones first */
195 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 196 return -1;
baf76283 197 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
198 return 1;
199
200 /* Lower priority values first */
201 if (x->priority < y->priority)
202 return -1;
203 if (x->priority > y->priority)
204 return 1;
205
206 /* Stability for the rest */
207 if (x < y)
208 return -1;
dfcd88f6 209 if (x > y)
fd38203a
LP
210 return 1;
211
212 return 0;
213}
214
c2ba3ad6 215static int earliest_time_prioq_compare(const void *a, const void *b) {
fd38203a
LP
216 const sd_event_source *x = a, *y = b;
217
218 assert(x->type == SOURCE_MONOTONIC || x->type == SOURCE_REALTIME);
219 assert(y->type == SOURCE_MONOTONIC || y->type == SOURCE_REALTIME);
220
baf76283
LP
221 /* Enabled ones first */
222 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 223 return -1;
baf76283 224 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
225 return 1;
226
227 /* Move the pending ones to the end */
228 if (!x->pending && y->pending)
229 return -1;
230 if (x->pending && !y->pending)
231 return 1;
232
233 /* Order by time */
234 if (x->time.next < y->time.next)
235 return -1;
236 if (x->time.next > y->time.next)
a99badf5 237 return 1;
fd38203a
LP
238
239 /* Stability for the rest */
240 if (x < y)
241 return -1;
dfcd88f6 242 if (x > y)
fd38203a
LP
243 return 1;
244
245 return 0;
246}
247
c2ba3ad6
LP
248static int latest_time_prioq_compare(const void *a, const void *b) {
249 const sd_event_source *x = a, *y = b;
250
da7e457c
LP
251 assert((x->type == SOURCE_MONOTONIC && y->type == SOURCE_MONOTONIC) ||
252 (x->type == SOURCE_REALTIME && y->type == SOURCE_REALTIME));
c2ba3ad6 253
baf76283
LP
254 /* Enabled ones first */
255 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
c2ba3ad6 256 return -1;
baf76283 257 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
c2ba3ad6
LP
258 return 1;
259
260 /* Move the pending ones to the end */
261 if (!x->pending && y->pending)
262 return -1;
263 if (x->pending && !y->pending)
264 return 1;
265
266 /* Order by time */
267 if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
268 return -1;
269 if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
a99badf5 270 return 1;
c2ba3ad6
LP
271
272 /* Stability for the rest */
273 if (x < y)
274 return -1;
275 if (x > y)
276 return 1;
277
278 return 0;
279}
280
da7e457c
LP
281static int quit_prioq_compare(const void *a, const void *b) {
282 const sd_event_source *x = a, *y = b;
283
284 assert(x->type == SOURCE_QUIT);
285 assert(y->type == SOURCE_QUIT);
286
baf76283
LP
287 /* Enabled ones first */
288 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
da7e457c 289 return -1;
baf76283 290 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
da7e457c
LP
291 return 1;
292
293 /* Lower priority values first */
294 if (x->priority < y->priority)
295 return -1;
296 if (x->priority > y->priority)
297 return 1;
298
299 /* Stability for the rest */
300 if (x < y)
301 return -1;
302 if (x > y)
303 return 1;
304
305 return 0;
306}
307
fd38203a
LP
308static void event_free(sd_event *e) {
309 assert(e);
310
afc6adb5
LP
311 if (e->default_event_ptr)
312 *(e->default_event_ptr) = NULL;
313
fd38203a
LP
314 if (e->epoll_fd >= 0)
315 close_nointr_nofail(e->epoll_fd);
316
317 if (e->signal_fd >= 0)
318 close_nointr_nofail(e->signal_fd);
319
320 if (e->realtime_fd >= 0)
321 close_nointr_nofail(e->realtime_fd);
322
323 if (e->monotonic_fd >= 0)
324 close_nointr_nofail(e->monotonic_fd);
325
326 prioq_free(e->pending);
327 prioq_free(e->prepare);
c2ba3ad6
LP
328 prioq_free(e->monotonic_earliest);
329 prioq_free(e->monotonic_latest);
330 prioq_free(e->realtime_earliest);
331 prioq_free(e->realtime_latest);
da7e457c 332 prioq_free(e->quit);
fd38203a
LP
333
334 free(e->signal_sources);
335
336 hashmap_free(e->child_sources);
337 free(e);
338}
339
f7262a9f 340_public_ int sd_event_new(sd_event** ret) {
fd38203a
LP
341 sd_event *e;
342 int r;
343
305f78bf 344 assert_return(ret, -EINVAL);
fd38203a
LP
345
346 e = new0(sd_event, 1);
347 if (!e)
348 return -ENOMEM;
349
da7e457c 350 e->n_ref = 1;
fd38203a
LP
351 e->signal_fd = e->realtime_fd = e->monotonic_fd = e->epoll_fd = -1;
352 e->realtime_next = e->monotonic_next = (usec_t) -1;
eaa3cbef 353 e->original_pid = getpid();
fd38203a
LP
354
355 assert_se(sigemptyset(&e->sigset) == 0);
356
357 e->pending = prioq_new(pending_prioq_compare);
358 if (!e->pending) {
359 r = -ENOMEM;
360 goto fail;
361 }
362
363 e->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
364 if (e->epoll_fd < 0) {
365 r = -errno;
366 goto fail;
367 }
368
369 *ret = e;
370 return 0;
371
372fail:
373 event_free(e);
374 return r;
375}
376
f7262a9f 377_public_ sd_event* sd_event_ref(sd_event *e) {
305f78bf 378 assert_return(e, NULL);
fd38203a 379
da7e457c
LP
380 assert(e->n_ref >= 1);
381 e->n_ref++;
fd38203a
LP
382
383 return e;
384}
385
f7262a9f 386_public_ sd_event* sd_event_unref(sd_event *e) {
305f78bf 387 assert_return(e, NULL);
fd38203a 388
da7e457c
LP
389 assert(e->n_ref >= 1);
390 e->n_ref--;
391
392 if (e->n_ref <= 0)
fd38203a
LP
393 event_free(e);
394
395 return NULL;
396}
397
eaa3cbef
LP
398static bool event_pid_changed(sd_event *e) {
399 assert(e);
400
401 /* We don't support people creating am event loop and keeping
402 * it around over a fork(). Let's complain. */
403
404 return e->original_pid != getpid();
405}
406
fd38203a
LP
407static int source_io_unregister(sd_event_source *s) {
408 int r;
409
410 assert(s);
411 assert(s->type == SOURCE_IO);
412
413 if (!s->io.registered)
414 return 0;
415
416 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL);
417 if (r < 0)
418 return -errno;
419
420 s->io.registered = false;
421 return 0;
422}
423
305f78bf
LP
424static int source_io_register(
425 sd_event_source *s,
426 int enabled,
427 uint32_t events) {
428
fd38203a
LP
429 struct epoll_event ev = {};
430 int r;
431
432 assert(s);
433 assert(s->type == SOURCE_IO);
baf76283 434 assert(enabled != SD_EVENT_OFF);
fd38203a
LP
435
436 ev.events = events;
437 ev.data.ptr = s;
438
baf76283 439 if (enabled == SD_EVENT_ONESHOT)
fd38203a
LP
440 ev.events |= EPOLLONESHOT;
441
442 if (s->io.registered)
443 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
444 else
445 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev);
446
447 if (r < 0)
448 return -errno;
449
450 s->io.registered = true;
451
452 return 0;
453}
454
455static void source_free(sd_event_source *s) {
456 assert(s);
457
458 if (s->event) {
459 switch (s->type) {
460
461 case SOURCE_IO:
462 if (s->io.fd >= 0)
463 source_io_unregister(s);
464
465 break;
466
467 case SOURCE_MONOTONIC:
c2ba3ad6
LP
468 prioq_remove(s->event->monotonic_earliest, s, &s->time.earliest_index);
469 prioq_remove(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
470 break;
471
472 case SOURCE_REALTIME:
c2ba3ad6
LP
473 prioq_remove(s->event->realtime_earliest, s, &s->time.earliest_index);
474 prioq_remove(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
475 break;
476
477 case SOURCE_SIGNAL:
478 if (s->signal.sig > 0) {
baf76283 479 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0)
fd38203a
LP
480 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
481
482 if (s->event->signal_sources)
483 s->event->signal_sources[s->signal.sig] = NULL;
484 }
485
486 break;
487
488 case SOURCE_CHILD:
489 if (s->child.pid > 0) {
baf76283
LP
490 if (s->enabled != SD_EVENT_OFF) {
491 assert(s->event->n_enabled_child_sources > 0);
492 s->event->n_enabled_child_sources--;
fd38203a
LP
493 }
494
495 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD])
496 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
497
498 hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
499 }
500
501 break;
da7e457c 502
0eb2e0e3
ZJS
503 case SOURCE_DEFER:
504 /* nothing */
505 break;
506
da7e457c
LP
507 case SOURCE_QUIT:
508 prioq_remove(s->event->quit, s, &s->quit.prioq_index);
509 break;
fd38203a
LP
510 }
511
512 if (s->pending)
513 prioq_remove(s->event->pending, s, &s->pending_index);
514
515 if (s->prepare)
516 prioq_remove(s->event->prepare, s, &s->prepare_index);
517
518 sd_event_unref(s->event);
519 }
520
521 free(s);
522}
523
524static int source_set_pending(sd_event_source *s, bool b) {
525 int r;
526
527 assert(s);
da7e457c 528 assert(s->type != SOURCE_QUIT);
fd38203a
LP
529
530 if (s->pending == b)
531 return 0;
532
533 s->pending = b;
534
535 if (b) {
536 s->pending_iteration = s->event->iteration;
537
538 r = prioq_put(s->event->pending, s, &s->pending_index);
539 if (r < 0) {
540 s->pending = false;
541 return r;
542 }
543 } else
544 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
545
2576a19e
LP
546 if (s->type == SOURCE_REALTIME) {
547 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
548 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
549 } else if (s->type == SOURCE_MONOTONIC) {
550 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
551 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
552 }
553
fd38203a
LP
554 return 0;
555}
556
557static sd_event_source *source_new(sd_event *e, EventSourceType type) {
558 sd_event_source *s;
559
560 assert(e);
561
562 s = new0(sd_event_source, 1);
563 if (!s)
564 return NULL;
565
da7e457c 566 s->n_ref = 1;
fd38203a
LP
567 s->event = sd_event_ref(e);
568 s->type = type;
fd38203a
LP
569 s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
570
571 return s;
572}
573
f7262a9f 574_public_ int sd_event_add_io(
fd38203a
LP
575 sd_event *e,
576 int fd,
577 uint32_t events,
718db961 578 sd_event_io_handler_t callback,
fd38203a
LP
579 void *userdata,
580 sd_event_source **ret) {
581
582 sd_event_source *s;
583 int r;
584
305f78bf
LP
585 assert_return(e, -EINVAL);
586 assert_return(fd >= 0, -EINVAL);
587 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
588 assert_return(callback, -EINVAL);
589 assert_return(ret, -EINVAL);
da7e457c 590 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 591 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
592
593 s = source_new(e, SOURCE_IO);
594 if (!s)
595 return -ENOMEM;
596
597 s->io.fd = fd;
598 s->io.events = events;
599 s->io.callback = callback;
600 s->userdata = userdata;
baf76283 601 s->enabled = SD_EVENT_ON;
fd38203a 602
baf76283 603 r = source_io_register(s, s->enabled, events);
fd38203a
LP
604 if (r < 0) {
605 source_free(s);
606 return -errno;
607 }
608
609 *ret = s;
610 return 0;
611}
612
613static int event_setup_timer_fd(
614 sd_event *e,
615 EventSourceType type,
616 int *timer_fd,
617 clockid_t id) {
618
619 struct epoll_event ev = {};
620 int r, fd;
c2ba3ad6 621 sd_id128_t bootid;
fd38203a
LP
622
623 assert(e);
624 assert(timer_fd);
625
626 if (_likely_(*timer_fd >= 0))
627 return 0;
628
629 fd = timerfd_create(id, TFD_NONBLOCK|TFD_CLOEXEC);
630 if (fd < 0)
631 return -errno;
632
633 ev.events = EPOLLIN;
634 ev.data.ptr = INT_TO_PTR(type);
635
636 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
637 if (r < 0) {
638 close_nointr_nofail(fd);
639 return -errno;
640 }
641
c2ba3ad6
LP
642 /* When we sleep for longer, we try to realign the wakeup to
643 the same time wihtin each second, so that events all across
644 the system can be coalesced into a single CPU
645 wakeup. However, let's take some system-specific randomness
646 for this value, so that in a network of systems with synced
647 clocks timer events are distributed a bit. Here, we
648 calculate a perturbation usec offset from the boot ID. */
649
650 if (sd_id128_get_boot(&bootid) >= 0)
651 e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_SEC;
652
fd38203a
LP
653 *timer_fd = fd;
654 return 0;
655}
656
657static int event_add_time_internal(
658 sd_event *e,
659 EventSourceType type,
660 int *timer_fd,
661 clockid_t id,
c2ba3ad6
LP
662 Prioq **earliest,
663 Prioq **latest,
fd38203a 664 uint64_t usec,
c2ba3ad6 665 uint64_t accuracy,
718db961 666 sd_event_time_handler_t callback,
fd38203a
LP
667 void *userdata,
668 sd_event_source **ret) {
669
670 sd_event_source *s;
671 int r;
672
305f78bf
LP
673 assert_return(e, -EINVAL);
674 assert_return(callback, -EINVAL);
675 assert_return(ret, -EINVAL);
676 assert_return(usec != (uint64_t) -1, -EINVAL);
677 assert_return(accuracy != (uint64_t) -1, -EINVAL);
da7e457c 678 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 679 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
680
681 assert(timer_fd);
c2ba3ad6
LP
682 assert(earliest);
683 assert(latest);
684
685 if (!*earliest) {
686 *earliest = prioq_new(earliest_time_prioq_compare);
687 if (!*earliest)
688 return -ENOMEM;
689 }
fd38203a 690
c2ba3ad6
LP
691 if (!*latest) {
692 *latest = prioq_new(latest_time_prioq_compare);
693 if (!*latest)
fd38203a
LP
694 return -ENOMEM;
695 }
696
697 if (*timer_fd < 0) {
698 r = event_setup_timer_fd(e, type, timer_fd, id);
699 if (r < 0)
700 return r;
701 }
702
703 s = source_new(e, type);
704 if (!s)
705 return -ENOMEM;
706
707 s->time.next = usec;
c2ba3ad6 708 s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy;
fd38203a 709 s->time.callback = callback;
da7e457c 710 s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL;
fd38203a 711 s->userdata = userdata;
baf76283 712 s->enabled = SD_EVENT_ONESHOT;
fd38203a 713
c2ba3ad6
LP
714 r = prioq_put(*earliest, s, &s->time.earliest_index);
715 if (r < 0)
716 goto fail;
717
718 r = prioq_put(*latest, s, &s->time.latest_index);
719 if (r < 0)
720 goto fail;
fd38203a
LP
721
722 *ret = s;
723 return 0;
c2ba3ad6
LP
724
725fail:
726 source_free(s);
727 return r;
fd38203a
LP
728}
729
f7262a9f
ZJS
730_public_ int sd_event_add_monotonic(sd_event *e,
731 uint64_t usec,
732 uint64_t accuracy,
718db961 733 sd_event_time_handler_t callback,
f7262a9f
ZJS
734 void *userdata,
735 sd_event_source **ret) {
736
c2ba3ad6 737 return event_add_time_internal(e, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
fd38203a
LP
738}
739
f7262a9f
ZJS
740_public_ int sd_event_add_realtime(sd_event *e,
741 uint64_t usec,
742 uint64_t accuracy,
718db961 743 sd_event_time_handler_t callback,
f7262a9f
ZJS
744 void *userdata,
745 sd_event_source **ret) {
746
c2ba3ad6 747 return event_add_time_internal(e, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
fd38203a
LP
748}
749
750static int event_update_signal_fd(sd_event *e) {
751 struct epoll_event ev = {};
752 bool add_to_epoll;
753 int r;
754
755 assert(e);
756
757 add_to_epoll = e->signal_fd < 0;
758
759 r = signalfd(e->signal_fd, &e->sigset, SFD_NONBLOCK|SFD_CLOEXEC);
760 if (r < 0)
761 return -errno;
762
763 e->signal_fd = r;
764
765 if (!add_to_epoll)
766 return 0;
767
768 ev.events = EPOLLIN;
769 ev.data.ptr = INT_TO_PTR(SOURCE_SIGNAL);
770
771 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->signal_fd, &ev);
772 if (r < 0) {
773 close_nointr_nofail(e->signal_fd);
774 e->signal_fd = -1;
775
776 return -errno;
777 }
778
779 return 0;
780}
781
f7262a9f 782_public_ int sd_event_add_signal(
305f78bf
LP
783 sd_event *e,
784 int sig,
718db961 785 sd_event_signal_handler_t callback,
305f78bf
LP
786 void *userdata,
787 sd_event_source **ret) {
788
fd38203a
LP
789 sd_event_source *s;
790 int r;
791
305f78bf
LP
792 assert_return(e, -EINVAL);
793 assert_return(sig > 0, -EINVAL);
794 assert_return(sig < _NSIG, -EINVAL);
795 assert_return(callback, -EINVAL);
796 assert_return(ret, -EINVAL);
da7e457c 797 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 798 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
799
800 if (!e->signal_sources) {
801 e->signal_sources = new0(sd_event_source*, _NSIG);
802 if (!e->signal_sources)
803 return -ENOMEM;
804 } else if (e->signal_sources[sig])
805 return -EBUSY;
806
807 s = source_new(e, SOURCE_SIGNAL);
808 if (!s)
809 return -ENOMEM;
810
811 s->signal.sig = sig;
812 s->signal.callback = callback;
813 s->userdata = userdata;
baf76283 814 s->enabled = SD_EVENT_ON;
fd38203a
LP
815
816 e->signal_sources[sig] = s;
817 assert_se(sigaddset(&e->sigset, sig) == 0);
818
baf76283 819 if (sig != SIGCHLD || e->n_enabled_child_sources == 0) {
fd38203a
LP
820 r = event_update_signal_fd(e);
821 if (r < 0) {
822 source_free(s);
823 return r;
824 }
825 }
826
827 *ret = s;
828 return 0;
829}
830
f7262a9f 831_public_ int sd_event_add_child(
305f78bf
LP
832 sd_event *e,
833 pid_t pid,
834 int options,
718db961 835 sd_event_child_handler_t callback,
305f78bf
LP
836 void *userdata,
837 sd_event_source **ret) {
838
fd38203a
LP
839 sd_event_source *s;
840 int r;
841
305f78bf
LP
842 assert_return(e, -EINVAL);
843 assert_return(pid > 1, -EINVAL);
844 assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
845 assert_return(options != 0, -EINVAL);
846 assert_return(callback, -EINVAL);
847 assert_return(ret, -EINVAL);
da7e457c 848 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 849 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
850
851 r = hashmap_ensure_allocated(&e->child_sources, trivial_hash_func, trivial_compare_func);
852 if (r < 0)
853 return r;
854
855 if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
856 return -EBUSY;
857
858 s = source_new(e, SOURCE_CHILD);
859 if (!s)
860 return -ENOMEM;
861
862 s->child.pid = pid;
863 s->child.options = options;
864 s->child.callback = callback;
865 s->userdata = userdata;
baf76283 866 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
867
868 r = hashmap_put(e->child_sources, INT_TO_PTR(pid), s);
869 if (r < 0) {
870 source_free(s);
871 return r;
872 }
873
baf76283 874 e->n_enabled_child_sources ++;
fd38203a
LP
875
876 assert_se(sigaddset(&e->sigset, SIGCHLD) == 0);
877
878 if (!e->signal_sources || !e->signal_sources[SIGCHLD]) {
879 r = event_update_signal_fd(e);
880 if (r < 0) {
881 source_free(s);
882 return -errno;
883 }
884 }
885
c2ba3ad6
LP
886 e->need_process_child = true;
887
fd38203a
LP
888 *ret = s;
889 return 0;
890}
891
f7262a9f 892_public_ int sd_event_add_defer(
305f78bf 893 sd_event *e,
718db961 894 sd_event_handler_t callback,
305f78bf
LP
895 void *userdata,
896 sd_event_source **ret) {
897
fd38203a
LP
898 sd_event_source *s;
899 int r;
900
305f78bf
LP
901 assert_return(e, -EINVAL);
902 assert_return(callback, -EINVAL);
903 assert_return(ret, -EINVAL);
da7e457c 904 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 905 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
906
907 s = source_new(e, SOURCE_DEFER);
908 if (!s)
909 return -ENOMEM;
910
911 s->defer.callback = callback;
912 s->userdata = userdata;
baf76283 913 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
914
915 r = source_set_pending(s, true);
916 if (r < 0) {
917 source_free(s);
918 return r;
919 }
920
921 *ret = s;
922 return 0;
923}
924
f7262a9f 925_public_ int sd_event_add_quit(
305f78bf 926 sd_event *e,
718db961 927 sd_event_handler_t callback,
305f78bf
LP
928 void *userdata,
929 sd_event_source **ret) {
930
da7e457c
LP
931 sd_event_source *s;
932 int r;
933
934 assert_return(e, -EINVAL);
935 assert_return(callback, -EINVAL);
305f78bf 936 assert_return(ret, -EINVAL);
da7e457c
LP
937 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
938 assert_return(!event_pid_changed(e), -ECHILD);
939
940 if (!e->quit) {
941 e->quit = prioq_new(quit_prioq_compare);
942 if (!e->quit)
943 return -ENOMEM;
944 }
945
946 s = source_new(e, SOURCE_QUIT);
fd38203a 947 if (!s)
da7e457c 948 return -ENOMEM;
fd38203a 949
da7e457c
LP
950 s->quit.callback = callback;
951 s->userdata = userdata;
952 s->quit.prioq_index = PRIOQ_IDX_NULL;
baf76283 953 s->enabled = SD_EVENT_ONESHOT;
da7e457c
LP
954
955 r = prioq_put(s->event->quit, s, &s->quit.prioq_index);
956 if (r < 0) {
957 source_free(s);
958 return r;
959 }
960
961 *ret = s;
962 return 0;
963}
964
f7262a9f 965_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
da7e457c
LP
966 assert_return(s, NULL);
967
968 assert(s->n_ref >= 1);
969 s->n_ref++;
fd38203a
LP
970
971 return s;
972}
973
f7262a9f 974_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
da7e457c 975 assert_return(s, NULL);
fd38203a 976
da7e457c
LP
977 assert(s->n_ref >= 1);
978 s->n_ref--;
979
980 if (s->n_ref <= 0)
fd38203a
LP
981 source_free(s);
982
983 return NULL;
984}
985
f7262a9f 986_public_ sd_event *sd_event_get(sd_event_source *s) {
305f78bf 987 assert_return(s, NULL);
eaa3cbef
LP
988
989 return s->event;
990}
991
f7262a9f 992_public_ int sd_event_source_get_pending(sd_event_source *s) {
305f78bf
LP
993 assert_return(s, -EINVAL);
994 assert_return(s->type != SOURCE_QUIT, -EDOM);
da7e457c 995 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 996 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
997
998 return s->pending;
999}
1000
f7262a9f 1001_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
305f78bf
LP
1002 assert_return(s, -EINVAL);
1003 assert_return(s->type == SOURCE_IO, -EDOM);
1004 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1005
1006 return s->io.fd;
1007}
1008
f7262a9f 1009_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
305f78bf
LP
1010 assert_return(s, -EINVAL);
1011 assert_return(events, -EINVAL);
1012 assert_return(s->type == SOURCE_IO, -EDOM);
1013 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1014
1015 *events = s->io.events;
1016 return 0;
1017}
1018
f7262a9f 1019_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
fd38203a
LP
1020 int r;
1021
305f78bf
LP
1022 assert_return(s, -EINVAL);
1023 assert_return(s->type == SOURCE_IO, -EDOM);
1024 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
da7e457c 1025 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1026 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1027
1028 if (s->io.events == events)
1029 return 0;
1030
baf76283 1031 if (s->enabled != SD_EVENT_OFF) {
e4715127 1032 r = source_io_register(s, s->enabled, events);
fd38203a
LP
1033 if (r < 0)
1034 return r;
1035 }
1036
1037 s->io.events = events;
503f39c3 1038 source_set_pending(s, false);
fd38203a
LP
1039
1040 return 0;
1041}
1042
f7262a9f 1043_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
305f78bf
LP
1044 assert_return(s, -EINVAL);
1045 assert_return(revents, -EINVAL);
1046 assert_return(s->type == SOURCE_IO, -EDOM);
1047 assert_return(s->pending, -ENODATA);
1048 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1049
1050 *revents = s->io.revents;
1051 return 0;
1052}
1053
f7262a9f 1054_public_ int sd_event_source_get_signal(sd_event_source *s) {
305f78bf
LP
1055 assert_return(s, -EINVAL);
1056 assert_return(s->type == SOURCE_SIGNAL, -EDOM);
1057 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1058
1059 return s->signal.sig;
1060}
1061
f7262a9f 1062_public_ int sd_event_source_get_priority(sd_event_source *s, int *priority) {
305f78bf
LP
1063 assert_return(s, -EINVAL);
1064 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1065
1066 return s->priority;
1067}
1068
f7262a9f 1069_public_ int sd_event_source_set_priority(sd_event_source *s, int priority) {
305f78bf 1070 assert_return(s, -EINVAL);
da7e457c 1071 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1072 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1073
1074 if (s->priority == priority)
1075 return 0;
1076
1077 s->priority = priority;
1078
1079 if (s->pending)
c2ba3ad6 1080 prioq_reshuffle(s->event->pending, s, &s->pending_index);
fd38203a
LP
1081
1082 if (s->prepare)
c2ba3ad6 1083 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
fd38203a 1084
305f78bf
LP
1085 if (s->type == SOURCE_QUIT)
1086 prioq_reshuffle(s->event->quit, s, &s->quit.prioq_index);
1087
fd38203a
LP
1088 return 0;
1089}
1090
f7262a9f 1091_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
305f78bf
LP
1092 assert_return(s, -EINVAL);
1093 assert_return(m, -EINVAL);
1094 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1095
baf76283 1096 *m = s->enabled;
fd38203a
LP
1097 return 0;
1098}
1099
f7262a9f 1100_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
fd38203a
LP
1101 int r;
1102
305f78bf
LP
1103 assert_return(s, -EINVAL);
1104 assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL);
da7e457c 1105 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1106 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1107
baf76283 1108 if (s->enabled == m)
fd38203a
LP
1109 return 0;
1110
baf76283 1111 if (m == SD_EVENT_OFF) {
fd38203a
LP
1112
1113 switch (s->type) {
1114
1115 case SOURCE_IO:
1116 r = source_io_unregister(s);
1117 if (r < 0)
1118 return r;
1119
baf76283 1120 s->enabled = m;
fd38203a
LP
1121 break;
1122
1123 case SOURCE_MONOTONIC:
baf76283 1124 s->enabled = m;
c2ba3ad6
LP
1125 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1126 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
1127 break;
1128
1129 case SOURCE_REALTIME:
baf76283 1130 s->enabled = m;
c2ba3ad6
LP
1131 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1132 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
1133 break;
1134
1135 case SOURCE_SIGNAL:
baf76283
LP
1136 s->enabled = m;
1137 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1138 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
1139 event_update_signal_fd(s->event);
1140 }
1141
1142 break;
1143
1144 case SOURCE_CHILD:
baf76283 1145 s->enabled = m;
fd38203a 1146
baf76283
LP
1147 assert(s->event->n_enabled_child_sources > 0);
1148 s->event->n_enabled_child_sources--;
fd38203a
LP
1149
1150 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1151 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
1152 event_update_signal_fd(s->event);
1153 }
1154
1155 break;
1156
da7e457c 1157 case SOURCE_QUIT:
305f78bf
LP
1158 s->enabled = m;
1159 prioq_reshuffle(s->event->quit, s, &s->quit.prioq_index);
1160 break;
1161
1162 case SOURCE_DEFER:
baf76283 1163 s->enabled = m;
fd38203a
LP
1164 break;
1165 }
1166
1167 } else {
1168 switch (s->type) {
1169
1170 case SOURCE_IO:
1171 r = source_io_register(s, m, s->io.events);
1172 if (r < 0)
1173 return r;
1174
baf76283 1175 s->enabled = m;
fd38203a
LP
1176 break;
1177
1178 case SOURCE_MONOTONIC:
baf76283 1179 s->enabled = m;
c2ba3ad6
LP
1180 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1181 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
1182 break;
1183
1184 case SOURCE_REALTIME:
baf76283 1185 s->enabled = m;
c2ba3ad6
LP
1186 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1187 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
1188 break;
1189
1190 case SOURCE_SIGNAL:
baf76283 1191 s->enabled = m;
fd38203a 1192
baf76283 1193 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1194 assert_se(sigaddset(&s->event->sigset, s->signal.sig) == 0);
1195 event_update_signal_fd(s->event);
1196 }
1197 break;
1198
1199 case SOURCE_CHILD:
baf76283 1200 s->enabled = m;
fd38203a 1201
baf76283
LP
1202 if (s->enabled == SD_EVENT_OFF) {
1203 s->event->n_enabled_child_sources++;
fd38203a
LP
1204
1205 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1206 assert_se(sigaddset(&s->event->sigset, SIGCHLD) == 0);
1207 event_update_signal_fd(s->event);
1208 }
1209 }
1210 break;
1211
da7e457c 1212 case SOURCE_QUIT:
305f78bf
LP
1213 s->enabled = m;
1214 prioq_reshuffle(s->event->quit, s, &s->quit.prioq_index);
1215 break;
1216
1217 case SOURCE_DEFER:
baf76283 1218 s->enabled = m;
fd38203a
LP
1219 break;
1220 }
1221 }
1222
1223 if (s->pending)
1224 prioq_reshuffle(s->event->pending, s, &s->pending_index);
1225
1226 if (s->prepare)
1227 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
1228
1229 return 0;
1230}
1231
f7262a9f 1232_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1233 assert_return(s, -EINVAL);
1234 assert_return(usec, -EINVAL);
1235 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
1236 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1237
1238 *usec = s->time.next;
1239 return 0;
1240}
1241
f7262a9f 1242_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
305f78bf
LP
1243 assert_return(s, -EINVAL);
1244 assert_return(usec != (uint64_t) -1, -EINVAL);
1245 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
da7e457c 1246 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1247 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1248
fd38203a 1249 s->time.next = usec;
2576a19e 1250
0cc1125a 1251 source_set_pending(s, false);
fd38203a 1252
c2ba3ad6
LP
1253 if (s->type == SOURCE_REALTIME) {
1254 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1255 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
1256 } else {
1257 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1258 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
1259 }
fd38203a
LP
1260
1261 return 0;
1262}
1263
f7262a9f 1264_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1265 assert_return(s, -EINVAL);
1266 assert_return(usec, -EINVAL);
1267 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
1268 assert_return(!event_pid_changed(s->event), -ECHILD);
1269
1270 *usec = s->time.accuracy;
1271 return 0;
1272}
1273
f7262a9f 1274_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
305f78bf
LP
1275 assert_return(s, -EINVAL);
1276 assert_return(usec != (uint64_t) -1, -EINVAL);
1277 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
da7e457c 1278 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1279 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef
LP
1280
1281 if (usec == 0)
1282 usec = DEFAULT_ACCURACY_USEC;
1283
eaa3cbef
LP
1284 s->time.accuracy = usec;
1285
2576a19e
LP
1286 source_set_pending(s, false);
1287
eaa3cbef
LP
1288 if (s->type == SOURCE_REALTIME)
1289 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
1290 else
1291 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
1292
1293 return 0;
1294}
1295
f7262a9f 1296_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
4bee8012
LP
1297 assert_return(s, -EINVAL);
1298 assert_return(pid, -EINVAL);
1299 assert_return(s->type == SOURCE_CHILD, -EDOM);
1300 assert_return(!event_pid_changed(s->event), -ECHILD);
1301
1302 *pid = s->child.pid;
1303 return 0;
1304}
1305
718db961 1306_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
fd38203a
LP
1307 int r;
1308
da7e457c
LP
1309 assert_return(s, -EINVAL);
1310 assert_return(s->type != SOURCE_QUIT, -EDOM);
1311 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
1312 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1313
1314 if (s->prepare == callback)
1315 return 0;
1316
1317 if (callback && s->prepare) {
1318 s->prepare = callback;
1319 return 0;
1320 }
1321
1322 r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare);
1323 if (r < 0)
1324 return r;
1325
1326 s->prepare = callback;
1327
1328 if (callback) {
1329 r = prioq_put(s->event->prepare, s, &s->prepare_index);
1330 if (r < 0)
1331 return r;
1332 } else
1333 prioq_remove(s->event->prepare, s, &s->prepare_index);
1334
1335 return 0;
1336}
1337
f7262a9f 1338_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
da7e457c 1339 assert_return(s, NULL);
fd38203a
LP
1340
1341 return s->userdata;
1342}
1343
c2ba3ad6
LP
1344static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
1345 usec_t c;
1346 assert(e);
1347 assert(a <= b);
1348
1349 if (a <= 0)
1350 return 0;
1351
1352 if (b <= a + 1)
1353 return a;
1354
1355 /*
1356 Find a good time to wake up again between times a and b. We
1357 have two goals here:
1358
1359 a) We want to wake up as seldom as possible, hence prefer
1360 later times over earlier times.
1361
1362 b) But if we have to wake up, then let's make sure to
1363 dispatch as much as possible on the entire system.
1364
1365 We implement this by waking up everywhere at the same time
1366 within any given second if we can, synchronised via the
1367 perturbation value determined from the boot ID. If we can't,
1368 then we try to find the same spot in every a 250ms
1369 step. Otherwise, we pick the last possible time to wake up.
1370 */
1371
1372 c = (b / USEC_PER_SEC) * USEC_PER_SEC + e->perturb;
1373 if (c >= b) {
1374 if (_unlikely_(c < USEC_PER_SEC))
1375 return b;
1376
1377 c -= USEC_PER_SEC;
1378 }
1379
1380 if (c >= a)
1381 return c;
1382
1383 c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250));
1384 if (c >= b) {
1385 if (_unlikely_(c < USEC_PER_MSEC*250))
1386 return b;
1387
1388 c -= USEC_PER_MSEC*250;
1389 }
1390
1391 if (c >= a)
1392 return c;
1393
1394 return b;
1395}
1396
fd38203a
LP
1397static int event_arm_timer(
1398 sd_event *e,
1399 int timer_fd,
c2ba3ad6
LP
1400 Prioq *earliest,
1401 Prioq *latest,
fd38203a
LP
1402 usec_t *next) {
1403
1404 struct itimerspec its = {};
c2ba3ad6
LP
1405 sd_event_source *a, *b;
1406 usec_t t;
fd38203a
LP
1407 int r;
1408
1409 assert_se(e);
1410 assert_se(next);
1411
c2ba3ad6 1412 a = prioq_peek(earliest);
72aedc1e
LP
1413 if (!a || a->enabled == SD_EVENT_OFF) {
1414
1415 if (*next == (usec_t) -1)
1416 return 0;
1417
1418 /* disarm */
1419 r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
1420 if (r < 0)
1421 return r;
1422
1423 *next = (usec_t) -1;
1424
fd38203a 1425 return 0;
72aedc1e 1426 }
fd38203a 1427
c2ba3ad6 1428 b = prioq_peek(latest);
baf76283 1429 assert_se(b && b->enabled != SD_EVENT_OFF);
c2ba3ad6
LP
1430
1431 t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
1432 if (*next == t)
fd38203a
LP
1433 return 0;
1434
1435 assert_se(timer_fd >= 0);
1436
c2ba3ad6 1437 if (t == 0) {
fd38203a
LP
1438 /* We don' want to disarm here, just mean some time looooong ago. */
1439 its.it_value.tv_sec = 0;
1440 its.it_value.tv_nsec = 1;
1441 } else
c2ba3ad6 1442 timespec_store(&its.it_value, t);
fd38203a
LP
1443
1444 r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
1445 if (r < 0)
1446 return r;
1447
c2ba3ad6 1448 *next = t;
fd38203a
LP
1449 return 0;
1450}
1451
1452static int process_io(sd_event *e, sd_event_source *s, uint32_t events) {
1453 assert(e);
1454 assert(s);
1455 assert(s->type == SOURCE_IO);
1456
1457 s->io.revents = events;
1458
fd38203a
LP
1459 return source_set_pending(s, true);
1460}
1461
72aedc1e 1462static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
fd38203a
LP
1463 uint64_t x;
1464 ssize_t ss;
1465
1466 assert(e);
da7e457c 1467 assert(fd >= 0);
72aedc1e
LP
1468 assert(next);
1469
305f78bf 1470 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1471
1472 ss = read(fd, &x, sizeof(x));
1473 if (ss < 0) {
1474 if (errno == EAGAIN || errno == EINTR)
1475 return 0;
1476
1477 return -errno;
1478 }
1479
1480 if (ss != sizeof(x))
1481 return -EIO;
1482
72aedc1e
LP
1483 *next = (usec_t) -1;
1484
fd38203a
LP
1485 return 0;
1486}
1487
305f78bf
LP
1488static int process_timer(
1489 sd_event *e,
1490 usec_t n,
1491 Prioq *earliest,
1492 Prioq *latest) {
1493
fd38203a
LP
1494 sd_event_source *s;
1495 int r;
1496
1497 assert(e);
1498
1499 for (;;) {
c2ba3ad6 1500 s = prioq_peek(earliest);
fd38203a
LP
1501 if (!s ||
1502 s->time.next > n ||
baf76283 1503 s->enabled == SD_EVENT_OFF ||
fd38203a
LP
1504 s->pending)
1505 break;
1506
1507 r = source_set_pending(s, true);
1508 if (r < 0)
1509 return r;
1510
c2ba3ad6
LP
1511 prioq_reshuffle(earliest, s, &s->time.earliest_index);
1512 prioq_reshuffle(latest, s, &s->time.latest_index);
fd38203a
LP
1513 }
1514
1515 return 0;
1516}
1517
1518static int process_child(sd_event *e) {
1519 sd_event_source *s;
1520 Iterator i;
1521 int r;
1522
1523 assert(e);
1524
c2ba3ad6
LP
1525 e->need_process_child = false;
1526
fd38203a
LP
1527 /*
1528 So, this is ugly. We iteratively invoke waitid() with P_PID
1529 + WNOHANG for each PID we wait for, instead of using
1530 P_ALL. This is because we only want to get child
1531 information of very specific child processes, and not all
1532 of them. We might not have processed the SIGCHLD even of a
1533 previous invocation and we don't want to maintain a
1534 unbounded *per-child* event queue, hence we really don't
1535 want anything flushed out of the kernel's queue that we
1536 don't care about. Since this is O(n) this means that if you
1537 have a lot of processes you probably want to handle SIGCHLD
1538 yourself.
1539 */
1540
1541 HASHMAP_FOREACH(s, e->child_sources, i) {
1542 assert(s->type == SOURCE_CHILD);
1543
1544 if (s->pending)
1545 continue;
1546
baf76283 1547 if (s->enabled == SD_EVENT_OFF)
fd38203a
LP
1548 continue;
1549
1550 zero(s->child.siginfo);
1551 r = waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|s->child.options);
1552 if (r < 0)
1553 return -errno;
1554
1555 if (s->child.siginfo.si_pid != 0) {
1556 r = source_set_pending(s, true);
1557 if (r < 0)
1558 return r;
1559 }
1560 }
1561
fd38203a
LP
1562 return 0;
1563}
1564
1565static int process_signal(sd_event *e, uint32_t events) {
fd38203a 1566 bool read_one = false;
fd38203a
LP
1567 int r;
1568
da7e457c 1569 assert(e);
0eb2e0e3
ZJS
1570 assert(e->signal_sources);
1571
305f78bf 1572 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1573
1574 for (;;) {
0eb2e0e3
ZJS
1575 struct signalfd_siginfo si;
1576 ssize_t ss;
fd38203a
LP
1577 sd_event_source *s;
1578
1579 ss = read(e->signal_fd, &si, sizeof(si));
1580 if (ss < 0) {
1581 if (errno == EAGAIN || errno == EINTR)
1582 return read_one;
1583
1584 return -errno;
1585 }
1586
1587 if (ss != sizeof(si))
1588 return -EIO;
1589
1590 read_one = true;
1591
0eb2e0e3 1592 s = e->signal_sources[si.ssi_signo];
fd38203a
LP
1593 if (si.ssi_signo == SIGCHLD) {
1594 r = process_child(e);
1595 if (r < 0)
1596 return r;
0eb2e0e3 1597 if (r > 0 || !s)
fd38203a 1598 continue;
0eb2e0e3 1599 } else
fd38203a
LP
1600 if (!s)
1601 return -EIO;
fd38203a
LP
1602
1603 s->signal.siginfo = si;
1604 r = source_set_pending(s, true);
1605 if (r < 0)
1606 return r;
1607 }
1608
1609
1610 return 0;
1611}
1612
1613static int source_dispatch(sd_event_source *s) {
fe8245eb 1614 int r = 0;
fd38203a
LP
1615
1616 assert(s);
da7e457c 1617 assert(s->pending || s->type == SOURCE_QUIT);
fd38203a 1618
da7e457c
LP
1619 if (s->type != SOURCE_DEFER && s->type != SOURCE_QUIT) {
1620 r = source_set_pending(s, false);
1621 if (r < 0)
1622 return r;
1623 }
fd38203a 1624
baf76283
LP
1625 if (s->enabled == SD_EVENT_ONESHOT) {
1626 r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
1627 if (r < 0)
1628 return r;
1629 }
1630
b7484e2a
LP
1631 sd_event_source_ref(s);
1632
fd38203a
LP
1633 switch (s->type) {
1634
1635 case SOURCE_IO:
1636 r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata);
1637 break;
1638
1639 case SOURCE_MONOTONIC:
1640 r = s->time.callback(s, s->time.next, s->userdata);
1641 break;
1642
1643 case SOURCE_REALTIME:
1644 r = s->time.callback(s, s->time.next, s->userdata);
1645 break;
1646
1647 case SOURCE_SIGNAL:
1648 r = s->signal.callback(s, &s->signal.siginfo, s->userdata);
1649 break;
1650
1651 case SOURCE_CHILD:
1652 r = s->child.callback(s, &s->child.siginfo, s->userdata);
1653 break;
1654
1655 case SOURCE_DEFER:
1656 r = s->defer.callback(s, s->userdata);
1657 break;
da7e457c
LP
1658
1659 case SOURCE_QUIT:
1660 r = s->quit.callback(s, s->userdata);
1661 break;
fd38203a
LP
1662 }
1663
b7484e2a
LP
1664 sd_event_source_unref(s);
1665
fd38203a
LP
1666 return r;
1667}
1668
1669static int event_prepare(sd_event *e) {
1670 int r;
1671
1672 assert(e);
1673
1674 for (;;) {
1675 sd_event_source *s;
1676
1677 s = prioq_peek(e->prepare);
baf76283 1678 if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF)
fd38203a
LP
1679 break;
1680
1681 s->prepare_iteration = e->iteration;
1682 r = prioq_reshuffle(e->prepare, s, &s->prepare_index);
1683 if (r < 0)
1684 return r;
1685
1686 assert(s->prepare);
1687 r = s->prepare(s, s->userdata);
1688 if (r < 0)
1689 return r;
1690
1691 }
1692
1693 return 0;
1694}
1695
da7e457c
LP
1696static int dispatch_quit(sd_event *e) {
1697 sd_event_source *p;
1698 int r;
1699
1700 assert(e);
1701
1702 p = prioq_peek(e->quit);
baf76283 1703 if (!p || p->enabled == SD_EVENT_OFF) {
da7e457c
LP
1704 e->state = SD_EVENT_FINISHED;
1705 return 0;
1706 }
1707
1708 sd_event_ref(e);
1709 e->iteration++;
1710 e->state = SD_EVENT_QUITTING;
1711
1712 r = source_dispatch(p);
1713
1714 e->state = SD_EVENT_PASSIVE;
1715 sd_event_unref(e);
1716
1717 return r;
1718}
1719
c2ba3ad6
LP
1720static sd_event_source* event_next_pending(sd_event *e) {
1721 sd_event_source *p;
1722
da7e457c
LP
1723 assert(e);
1724
c2ba3ad6
LP
1725 p = prioq_peek(e->pending);
1726 if (!p)
1727 return NULL;
1728
baf76283 1729 if (p->enabled == SD_EVENT_OFF)
c2ba3ad6
LP
1730 return NULL;
1731
1732 return p;
1733}
1734
f7262a9f 1735_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
fd38203a
LP
1736 struct epoll_event ev_queue[EPOLL_QUEUE_MAX];
1737 sd_event_source *p;
305f78bf 1738 int r, i, m;
fd38203a 1739
da7e457c
LP
1740 assert_return(e, -EINVAL);
1741 assert_return(!event_pid_changed(e), -ECHILD);
1742 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1743 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
1744
1745 if (e->quit_requested)
1746 return dispatch_quit(e);
fd38203a 1747
da7e457c 1748 sd_event_ref(e);
fd38203a 1749 e->iteration++;
da7e457c 1750 e->state = SD_EVENT_RUNNING;
fd38203a
LP
1751
1752 r = event_prepare(e);
1753 if (r < 0)
da7e457c 1754 goto finish;
fd38203a 1755
c2ba3ad6
LP
1756 if (event_next_pending(e) || e->need_process_child)
1757 timeout = 0;
fd38203a 1758
c2ba3ad6
LP
1759 if (timeout > 0) {
1760 r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
1761 if (r < 0)
da7e457c 1762 goto finish;
fd38203a 1763
c2ba3ad6
LP
1764 r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
1765 if (r < 0)
da7e457c 1766 goto finish;
fd38203a
LP
1767 }
1768
c2ba3ad6
LP
1769 m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
1770 timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
da7e457c 1771 if (m < 0) {
d09d5ecd 1772 r = errno == EAGAIN || errno == EINTR ? 0 : -errno;
da7e457c
LP
1773 goto finish;
1774 }
fd38203a 1775
46e8c825 1776 dual_timestamp_get(&e->timestamp);
fd38203a
LP
1777
1778 for (i = 0; i < m; i++) {
1779
1780 if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_MONOTONIC))
72aedc1e 1781 r = flush_timer(e, e->monotonic_fd, ev_queue[i].events, &e->monotonic_next);
fd38203a 1782 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_REALTIME))
72aedc1e 1783 r = flush_timer(e, e->realtime_fd, ev_queue[i].events, &e->realtime_next);
fd38203a
LP
1784 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_SIGNAL))
1785 r = process_signal(e, ev_queue[i].events);
1786 else
1787 r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
1788
1789 if (r < 0)
da7e457c 1790 goto finish;
fd38203a
LP
1791 }
1792
46e8c825 1793 r = process_timer(e, e->timestamp.monotonic, e->monotonic_earliest, e->monotonic_latest);
fd38203a 1794 if (r < 0)
da7e457c 1795 goto finish;
fd38203a 1796
46e8c825 1797 r = process_timer(e, e->timestamp.realtime, e->realtime_earliest, e->realtime_latest);
fd38203a 1798 if (r < 0)
da7e457c 1799 goto finish;
fd38203a 1800
c2ba3ad6 1801 if (e->need_process_child) {
fd38203a
LP
1802 r = process_child(e);
1803 if (r < 0)
da7e457c 1804 goto finish;
fd38203a
LP
1805 }
1806
c2ba3ad6 1807 p = event_next_pending(e);
da7e457c
LP
1808 if (!p) {
1809 r = 0;
1810 goto finish;
1811 }
1812
1813 r = source_dispatch(p);
fd38203a 1814
da7e457c
LP
1815finish:
1816 e->state = SD_EVENT_PASSIVE;
1817 sd_event_unref(e);
1818
1819 return r;
fd38203a
LP
1820}
1821
f7262a9f 1822_public_ int sd_event_loop(sd_event *e) {
fd38203a
LP
1823 int r;
1824
da7e457c
LP
1825 assert_return(e, -EINVAL);
1826 assert_return(!event_pid_changed(e), -ECHILD);
1827 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
1828
1829 sd_event_ref(e);
fd38203a 1830
da7e457c 1831 while (e->state != SD_EVENT_FINISHED) {
fd38203a
LP
1832 r = sd_event_run(e, (uint64_t) -1);
1833 if (r < 0)
da7e457c 1834 goto finish;
fd38203a
LP
1835 }
1836
da7e457c
LP
1837 r = 0;
1838
1839finish:
1840 sd_event_unref(e);
1841 return r;
fd38203a
LP
1842}
1843
f7262a9f 1844_public_ int sd_event_get_state(sd_event *e) {
da7e457c
LP
1845 assert_return(e, -EINVAL);
1846 assert_return(!event_pid_changed(e), -ECHILD);
1847
1848 return e->state;
1849}
1850
f7262a9f 1851_public_ int sd_event_get_quit(sd_event *e) {
da7e457c
LP
1852 assert_return(e, -EINVAL);
1853 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1854
da7e457c 1855 return e->quit_requested;
fd38203a
LP
1856}
1857
f7262a9f 1858_public_ int sd_event_request_quit(sd_event *e) {
da7e457c
LP
1859 assert_return(e, -EINVAL);
1860 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1861 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1862
da7e457c 1863 e->quit_requested = true;
fd38203a
LP
1864 return 0;
1865}
46e8c825 1866
f7262a9f 1867_public_ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
46e8c825
LP
1868 assert_return(e, -EINVAL);
1869 assert_return(usec, -EINVAL);
1870 assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
1871 assert_return(!event_pid_changed(e), -ECHILD);
1872
1873 *usec = e->timestamp.realtime;
1874 return 0;
1875}
1876
f7262a9f 1877_public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
46e8c825
LP
1878 assert_return(e, -EINVAL);
1879 assert_return(usec, -EINVAL);
1880 assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
1881 assert_return(!event_pid_changed(e), -ECHILD);
1882
1883 *usec = e->timestamp.monotonic;
1884 return 0;
1885}
afc6adb5
LP
1886
1887_public_ int sd_event_default(sd_event **ret) {
1888
1889 static __thread sd_event *default_event = NULL;
1890 sd_event *e;
1891 int r;
1892
1893 if (!ret)
1894 return !!default_event;
1895
1896 if (default_event) {
1897 *ret = sd_event_ref(default_event);
1898 return 0;
1899 }
1900
1901 r = sd_event_new(&e);
1902 if (r < 0)
1903 return r;
1904
1905 e->default_event_ptr = &default_event;
1906 e->tid = gettid();
1907 default_event = e;
1908
1909 *ret = e;
1910 return 1;
1911}
1912
1913_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
1914 assert_return(e, -EINVAL);
1915 assert_return(tid, -EINVAL);
76b54375 1916 assert_return(!event_pid_changed(e), -ECHILD);
afc6adb5 1917
76b54375
LP
1918 if (e->tid != 0) {
1919 *tid = e->tid;
1920 return 0;
1921 }
1922
1923 return -ENXIO;
afc6adb5 1924}