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