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