chiark / gitweb /
shell-completion: busctl
[elogind.git] / src / libsystemd-bus / sd-event.c
index 9c641c9a8ec7e10c08608a0f8e2f74c68d6e9148..b5ddf71ebede89439e76adf1a3ba33fab830be05 100644 (file)
 #include <sys/timerfd.h>
 #include <sys/wait.h>
 
 #include <sys/timerfd.h>
 #include <sys/wait.h>
 
+#include "sd-id128.h"
 #include "macro.h"
 #include "prioq.h"
 #include "hashmap.h"
 #include "util.h"
 #include "time-util.h"
 #include "macro.h"
 #include "prioq.h"
 #include "hashmap.h"
 #include "util.h"
 #include "time-util.h"
-#include "sd-id128.h"
+#include "missing.h"
 
 #include "sd-event.h"
 
 
 #include "sd-event.h"
 
@@ -50,7 +51,7 @@ struct sd_event_source {
 
         sd_event *event;
         void *userdata;
 
         sd_event *event;
         void *userdata;
-        sd_prepare_handler_t prepare;
+        sd_event_handler_t prepare;
 
         EventSourceType type:4;
         int enabled:3;
 
         EventSourceType type:4;
         int enabled:3;
@@ -64,34 +65,34 @@ struct sd_event_source {
 
         union {
                 struct {
 
         union {
                 struct {
-                        sd_io_handler_t callback;
+                        sd_event_io_handler_t callback;
                         int fd;
                         uint32_t events;
                         uint32_t revents;
                         bool registered:1;
                 } io;
                 struct {
                         int fd;
                         uint32_t events;
                         uint32_t revents;
                         bool registered:1;
                 } io;
                 struct {
-                        sd_time_handler_t callback;
+                        sd_event_time_handler_t callback;
                         usec_t next, accuracy;
                         unsigned earliest_index;
                         unsigned latest_index;
                 } time;
                 struct {
                         usec_t next, accuracy;
                         unsigned earliest_index;
                         unsigned latest_index;
                 } time;
                 struct {
-                        sd_signal_handler_t callback;
+                        sd_event_signal_handler_t callback;
                         struct signalfd_siginfo siginfo;
                         int sig;
                 } signal;
                 struct {
                         struct signalfd_siginfo siginfo;
                         int sig;
                 } signal;
                 struct {
-                        sd_child_handler_t callback;
+                        sd_event_child_handler_t callback;
                         siginfo_t siginfo;
                         pid_t pid;
                         int options;
                 } child;
                 struct {
                         siginfo_t siginfo;
                         pid_t pid;
                         int options;
                 } child;
                 struct {
-                        sd_defer_handler_t callback;
+                        sd_event_handler_t callback;
                 } defer;
                 struct {
                 } defer;
                 struct {
-                        sd_quit_handler_t callback;
+                        sd_event_handler_t callback;
                         unsigned prioq_index;
                 } quit;
         };
                         unsigned prioq_index;
                 } quit;
         };
@@ -138,6 +139,9 @@ struct sd_event {
 
         bool quit_requested:1;
         bool need_process_child:1;
 
         bool quit_requested:1;
         bool need_process_child:1;
+
+        pid_t tid;
+        sd_event **default_event_ptr;
 };
 
 static int pending_prioq_compare(const void *a, const void *b) {
 };
 
 static int pending_prioq_compare(const void *a, const void *b) {
@@ -230,7 +234,7 @@ static int earliest_time_prioq_compare(const void *a, const void *b) {
         if (x->time.next < y->time.next)
                 return -1;
         if (x->time.next > y->time.next)
         if (x->time.next < y->time.next)
                 return -1;
         if (x->time.next > y->time.next)
-                return -1;
+                return 1;
 
         /* Stability for the rest */
         if (x < y)
 
         /* Stability for the rest */
         if (x < y)
@@ -263,7 +267,7 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
         if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
                 return -1;
         if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
         if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
                 return -1;
         if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
-                return -1;
+                return 1;
 
         /* Stability for the rest */
         if (x < y)
 
         /* Stability for the rest */
         if (x < y)
@@ -304,6 +308,9 @@ static int quit_prioq_compare(const void *a, const void *b) {
 static void event_free(sd_event *e) {
         assert(e);
 
 static void event_free(sd_event *e) {
         assert(e);
 
+        if (e->default_event_ptr)
+                *(e->default_event_ptr) = NULL;
+
         if (e->epoll_fd >= 0)
                 close_nointr_nofail(e->epoll_fd);
 
         if (e->epoll_fd >= 0)
                 close_nointr_nofail(e->epoll_fd);
 
@@ -536,6 +543,14 @@ static int source_set_pending(sd_event_source *s, bool b) {
         } else
                 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
 
         } else
                 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
 
+        if (s->type == SOURCE_REALTIME) {
+                prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
+                prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
+        } else if (s->type == SOURCE_MONOTONIC) {
+                prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
+                prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
+        }
+
         return 0;
 }
 
         return 0;
 }
 
@@ -560,7 +575,7 @@ _public_ int sd_event_add_io(
                 sd_event *e,
                 int fd,
                 uint32_t events,
                 sd_event *e,
                 int fd,
                 uint32_t events,
-                sd_io_handler_t callback,
+                sd_event_io_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -569,7 +584,7 @@ _public_ int sd_event_add_io(
 
         assert_return(e, -EINVAL);
         assert_return(fd >= 0, -EINVAL);
 
         assert_return(e, -EINVAL);
         assert_return(fd >= 0, -EINVAL);
-        assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
+        assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
         assert_return(callback, -EINVAL);
         assert_return(ret, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(callback, -EINVAL);
         assert_return(ret, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
@@ -625,15 +640,16 @@ static int event_setup_timer_fd(
         }
 
         /* When we sleep for longer, we try to realign the wakeup to
         }
 
         /* When we sleep for longer, we try to realign the wakeup to
-           the same time wihtin each second, so that events all across
-           the system can be coalesced into a single CPU
-           wakeup. However, let's take some system-specific randomness
-           for this value, so that in a network of systems with synced
-           clocks timer events are distributed a bit. Here, we
-           calculate a perturbation usec offset from the boot ID. */
+           the same time wihtin each minute/second/250ms, so that
+           events all across the system can be coalesced into a single
+           CPU wakeup. However, let's take some system-specific
+           randomness for this value, so that in a network of systems
+           with synced clocks timer events are distributed a
+           bit. Here, we calculate a perturbation usec offset from the
+           boot ID. */
 
         if (sd_id128_get_boot(&bootid) >= 0)
 
         if (sd_id128_get_boot(&bootid) >= 0)
-                e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_SEC;
+                e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE;
 
         *timer_fd = fd;
         return 0;
 
         *timer_fd = fd;
         return 0;
@@ -648,7 +664,7 @@ static int event_add_time_internal(
                 Prioq **latest,
                 uint64_t usec,
                 uint64_t accuracy,
                 Prioq **latest,
                 uint64_t usec,
                 uint64_t accuracy,
-                sd_time_handler_t callback,
+                sd_event_time_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -715,7 +731,7 @@ fail:
 _public_ int sd_event_add_monotonic(sd_event *e,
                                     uint64_t usec,
                                     uint64_t accuracy,
 _public_ int sd_event_add_monotonic(sd_event *e,
                                     uint64_t usec,
                                     uint64_t accuracy,
-                                    sd_time_handler_t callback,
+                                    sd_event_time_handler_t callback,
                                     void *userdata,
                                     sd_event_source **ret) {
 
                                     void *userdata,
                                     sd_event_source **ret) {
 
@@ -725,7 +741,7 @@ _public_ int sd_event_add_monotonic(sd_event *e,
 _public_ int sd_event_add_realtime(sd_event *e,
                                    uint64_t usec,
                                    uint64_t accuracy,
 _public_ int sd_event_add_realtime(sd_event *e,
                                    uint64_t usec,
                                    uint64_t accuracy,
-                                   sd_time_handler_t callback,
+                                   sd_event_time_handler_t callback,
                                    void *userdata,
                                    sd_event_source **ret) {
 
                                    void *userdata,
                                    sd_event_source **ret) {
 
@@ -767,7 +783,7 @@ static int event_update_signal_fd(sd_event *e) {
 _public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
 _public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
-                sd_signal_handler_t callback,
+                sd_event_signal_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -817,7 +833,7 @@ _public_ int sd_event_add_child(
                 sd_event *e,
                 pid_t pid,
                 int options,
                 sd_event *e,
                 pid_t pid,
                 int options,
-                sd_child_handler_t callback,
+                sd_event_child_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -876,7 +892,7 @@ _public_ int sd_event_add_child(
 
 _public_ int sd_event_add_defer(
                 sd_event *e,
 
 _public_ int sd_event_add_defer(
                 sd_event *e,
-                sd_defer_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -909,7 +925,7 @@ _public_ int sd_event_add_defer(
 
 _public_ int sd_event_add_quit(
                 sd_event *e,
 
 _public_ int sd_event_add_quit(
                 sd_event *e,
-                sd_quit_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -968,7 +984,7 @@ _public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
         return NULL;
 }
 
         return NULL;
 }
 
-_public_ sd_event *sd_event_get(sd_event_source *s) {
+_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
         assert_return(s, NULL);
 
         return s->event;
         assert_return(s, NULL);
 
         return s->event;
@@ -1006,7 +1022,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
 
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
 
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
-        assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
+        assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
@@ -1020,6 +1036,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
         }
 
         s->io.events = events;
         }
 
         s->io.events = events;
+        source_set_pending(s, false);
 
         return 0;
 }
 
         return 0;
 }
@@ -1230,11 +1247,10 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
-        if (s->time.next == usec)
-                return 0;
-
         s->time.next = usec;
 
         s->time.next = usec;
 
+        source_set_pending(s, false);
+
         if (s->type == SOURCE_REALTIME) {
                 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
                 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
         if (s->type == SOURCE_REALTIME) {
                 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
                 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
@@ -1266,11 +1282,10 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
         if (usec == 0)
                 usec = DEFAULT_ACCURACY_USEC;
 
         if (usec == 0)
                 usec = DEFAULT_ACCURACY_USEC;
 
-        if (s->time.accuracy == usec)
-                return 0;
-
         s->time.accuracy = usec;
 
         s->time.accuracy = usec;
 
+        source_set_pending(s, false);
+
         if (s->type == SOURCE_REALTIME)
                 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
         else
         if (s->type == SOURCE_REALTIME)
                 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
         else
@@ -1289,7 +1304,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         return 0;
 }
 
         return 0;
 }
 
-_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback) {
+_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
         int r;
 
         assert_return(s, -EINVAL);
         int r;
 
         assert_return(s, -EINVAL);
@@ -1349,13 +1364,24 @@ static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
              dispatch as much as possible on the entire system.
 
           We implement this by waking up everywhere at the same time
              dispatch as much as possible on the entire system.
 
           We implement this by waking up everywhere at the same time
-          within any given second if we can, synchronised via the
+          within any given minute if we can, synchronised via the
           perturbation value determined from the boot ID. If we can't,
           perturbation value determined from the boot ID. If we can't,
-          then we try to find the same spot in every a 250ms
+          then we try to find the same spot in every 1s and then 250ms
           step. Otherwise, we pick the last possible time to wake up.
         */
 
           step. Otherwise, we pick the last possible time to wake up.
         */
 
-        c = (b / USEC_PER_SEC) * USEC_PER_SEC + e->perturb;
+        c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb;
+        if (c >= b) {
+                if (_unlikely_(c < USEC_PER_MINUTE))
+                        return b;
+
+                c -= USEC_PER_MINUTE;
+        }
+
+        if (c >= a)
+                return c;
+
+        c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC);
         if (c >= b) {
                 if (_unlikely_(c < USEC_PER_SEC))
                         return b;
         if (c >= b) {
                 if (_unlikely_(c < USEC_PER_SEC))
                         return b;
@@ -1398,6 +1424,9 @@ static int event_arm_timer(
         a = prioq_peek(earliest);
         if (!a || a->enabled == SD_EVENT_OFF) {
 
         a = prioq_peek(earliest);
         if (!a || a->enabled == SD_EVENT_OFF) {
 
+                if (timer_fd < 0)
+                        return 0;
+
                 if (*next == (usec_t) -1)
                         return 0;
 
                 if (*next == (usec_t) -1)
                         return 0;
 
@@ -1614,6 +1643,8 @@ static int source_dispatch(sd_event_source *s) {
                         return r;
         }
 
                         return r;
         }
 
+        sd_event_source_ref(s);
+
         switch (s->type) {
 
         case SOURCE_IO:
         switch (s->type) {
 
         case SOURCE_IO:
@@ -1645,6 +1676,8 @@ static int source_dispatch(sd_event_source *s) {
                 break;
         }
 
                 break;
         }
 
+        sd_event_source_unref(s);
+
         return r;
 }
 
         return r;
 }
 
@@ -1735,18 +1768,16 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
         if (r < 0)
                 goto finish;
 
-        if (event_next_pending(e) || e->need_process_child)
-                timeout = 0;
+        r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
+        if (r < 0)
+                goto finish;
 
 
-        if (timeout > 0) {
-                r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
-                if (r < 0)
-                        goto finish;
+        r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
+        if (r < 0)
+                goto finish;
 
 
-                r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
-                if (r < 0)
-                        goto finish;
-        }
+        if (event_next_pending(e) || e->need_process_child)
+                timeout = 0;
 
         m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
                        timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
 
         m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
                        timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
@@ -1865,3 +1896,42 @@ _public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
         *usec = e->timestamp.monotonic;
         return 0;
 }
         *usec = e->timestamp.monotonic;
         return 0;
 }
+
+_public_ int sd_event_default(sd_event **ret) {
+
+        static __thread sd_event *default_event = NULL;
+        sd_event *e;
+        int r;
+
+        if (!ret)
+                return !!default_event;
+
+        if (default_event) {
+                *ret = sd_event_ref(default_event);
+                return 0;
+        }
+
+        r = sd_event_new(&e);
+        if (r < 0)
+                return r;
+
+        e->default_event_ptr = &default_event;
+        e->tid = gettid();
+        default_event = e;
+
+        *ret = e;
+        return 1;
+}
+
+_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
+        assert_return(e, -EINVAL);
+        assert_return(tid, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+
+        if (e->tid != 0) {
+                *tid = e->tid;
+                return 0;
+        }
+
+        return -ENXIO;
+}