chiark / gitweb /
event: allow EPOLLET as event flag
[elogind.git] / src / libsystemd-bus / sd-event.c
index ace97dc7393767f3fbdfa22a11cdba552b2557df..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);
 
@@ -330,7 +337,7 @@ static void event_free(sd_event *e) {
         free(e);
 }
 
         free(e);
 }
 
-int sd_event_new(sd_event** ret) {
+_public_ int sd_event_new(sd_event** ret) {
         sd_event *e;
         int r;
 
         sd_event *e;
         int r;
 
@@ -367,7 +374,7 @@ fail:
         return r;
 }
 
         return r;
 }
 
-sd_event* sd_event_ref(sd_event *e) {
+_public_ sd_event* sd_event_ref(sd_event *e) {
         assert_return(e, NULL);
 
         assert(e->n_ref >= 1);
         assert_return(e, NULL);
 
         assert(e->n_ref >= 1);
@@ -376,7 +383,7 @@ sd_event* sd_event_ref(sd_event *e) {
         return e;
 }
 
         return e;
 }
 
-sd_event* sd_event_unref(sd_event *e) {
+_public_ sd_event* sd_event_unref(sd_event *e) {
         assert_return(e, NULL);
 
         assert(e->n_ref >= 1);
         assert_return(e, NULL);
 
         assert(e->n_ref >= 1);
@@ -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;
 }
 
@@ -556,11 +571,11 @@ static sd_event_source *source_new(sd_event *e, EventSourceType type) {
         return s;
 }
 
         return s;
 }
 
-int sd_event_add_io(
+_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 @@ 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) {
 
@@ -712,11 +728,23 @@ fail:
         return r;
 }
 
         return r;
 }
 
-int sd_event_add_monotonic(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **ret) {
+_public_ int sd_event_add_monotonic(sd_event *e,
+                                    uint64_t usec,
+                                    uint64_t accuracy,
+                                    sd_event_time_handler_t callback,
+                                    void *userdata,
+                                    sd_event_source **ret) {
+
         return event_add_time_internal(e, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
 }
 
         return event_add_time_internal(e, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
 }
 
-int sd_event_add_realtime(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **ret) {
+_public_ int sd_event_add_realtime(sd_event *e,
+                                   uint64_t usec,
+                                   uint64_t accuracy,
+                                   sd_event_time_handler_t callback,
+                                   void *userdata,
+                                   sd_event_source **ret) {
+
         return event_add_time_internal(e, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
 }
 
         return event_add_time_internal(e, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
 }
 
@@ -752,10 +780,10 @@ static int event_update_signal_fd(sd_event *e) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_add_signal(
+_public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
                 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) {
 
@@ -801,11 +829,11 @@ int sd_event_add_signal(
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_add_child(
+_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) {
 
@@ -862,9 +890,9 @@ int sd_event_add_child(
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_add_defer(
+_public_ int sd_event_add_defer(
                 sd_event *e,
                 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) {
 
@@ -895,9 +923,9 @@ int sd_event_add_defer(
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_add_quit(
+_public_ int sd_event_add_quit(
                 sd_event *e,
                 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) {
 
@@ -935,7 +963,7 @@ int sd_event_add_quit(
         return 0;
 }
 
         return 0;
 }
 
-sd_event_source* sd_event_source_ref(sd_event_source *s) {
+_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
         assert_return(s, NULL);
 
         assert(s->n_ref >= 1);
         assert_return(s, NULL);
 
         assert(s->n_ref >= 1);
@@ -944,7 +972,7 @@ sd_event_source* sd_event_source_ref(sd_event_source *s) {
         return s;
 }
 
         return s;
 }
 
-sd_event_source* sd_event_source_unref(sd_event_source *s) {
+_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
         assert_return(s, NULL);
 
         assert(s->n_ref >= 1);
         assert_return(s, NULL);
 
         assert(s->n_ref >= 1);
@@ -956,13 +984,13 @@ sd_event_source* sd_event_source_unref(sd_event_source *s) {
         return NULL;
 }
 
         return NULL;
 }
 
-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;
 }
 
-int sd_event_source_get_pending(sd_event_source *s) {
+_public_ int sd_event_source_get_pending(sd_event_source *s) {
         assert_return(s, -EINVAL);
         assert_return(s->type != SOURCE_QUIT, -EDOM);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(s, -EINVAL);
         assert_return(s->type != SOURCE_QUIT, -EDOM);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
@@ -971,7 +999,7 @@ int sd_event_source_get_pending(sd_event_source *s) {
         return s->pending;
 }
 
         return s->pending;
 }
 
-int sd_event_source_get_io_fd(sd_event_source *s) {
+_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
         assert_return(!event_pid_changed(s->event), -ECHILD);
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
         assert_return(!event_pid_changed(s->event), -ECHILD);
@@ -979,7 +1007,7 @@ int sd_event_source_get_io_fd(sd_event_source *s) {
         return s->io.fd;
 }
 
         return s->io.fd;
 }
 
-int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
+_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
         assert_return(s, -EINVAL);
         assert_return(events, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(events, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
@@ -989,12 +1017,12 @@ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
+_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
         int r;
 
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
         int r;
 
         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);
 
@@ -1008,11 +1036,12 @@ 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;
 }
 
-int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
+_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
         assert_return(s, -EINVAL);
         assert_return(revents, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(revents, -EINVAL);
         assert_return(s->type == SOURCE_IO, -EDOM);
@@ -1023,7 +1052,7 @@ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_get_signal(sd_event_source *s) {
+_public_ int sd_event_source_get_signal(sd_event_source *s) {
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_SIGNAL, -EDOM);
         assert_return(!event_pid_changed(s->event), -ECHILD);
         assert_return(s, -EINVAL);
         assert_return(s->type == SOURCE_SIGNAL, -EDOM);
         assert_return(!event_pid_changed(s->event), -ECHILD);
@@ -1031,14 +1060,14 @@ int sd_event_source_get_signal(sd_event_source *s) {
         return s->signal.sig;
 }
 
         return s->signal.sig;
 }
 
-int sd_event_source_get_priority(sd_event_source *s, int *priority) {
+_public_ int sd_event_source_get_priority(sd_event_source *s, int *priority) {
         assert_return(s, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         return s->priority;
 }
 
         assert_return(s, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         return s->priority;
 }
 
-int sd_event_source_set_priority(sd_event_source *s, int priority) {
+_public_ int sd_event_source_set_priority(sd_event_source *s, int priority) {
         assert_return(s, -EINVAL);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
         assert_return(s, -EINVAL);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
@@ -1060,7 +1089,7 @@ int sd_event_source_set_priority(sd_event_source *s, int priority) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_get_enabled(sd_event_source *s, int *m) {
+_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
         assert_return(s, -EINVAL);
         assert_return(m, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
         assert_return(s, -EINVAL);
         assert_return(m, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
@@ -1069,7 +1098,7 @@ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_set_enabled(sd_event_source *s, int m) {
+_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
         int r;
 
         assert_return(s, -EINVAL);
         int r;
 
         assert_return(s, -EINVAL);
@@ -1201,7 +1230,7 @@ int sd_event_source_set_enabled(sd_event_source *s, int m) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
+_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
         assert_return(s, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
@@ -1211,18 +1240,17 @@ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
+_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         assert_return(s, -EINVAL);
         assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         assert_return(s, -EINVAL);
         assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
         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);
@@ -1234,7 +1262,7 @@ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
+_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
         assert_return(s, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
@@ -1244,7 +1272,7 @@ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
+_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
         assert_return(s, -EINVAL);
         assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
@@ -1254,11 +1282,10 @@ 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
@@ -1267,7 +1294,7 @@ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
+_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         assert_return(s, -EINVAL);
         assert_return(pid, -EINVAL);
         assert_return(s->type == SOURCE_CHILD, -EDOM);
         assert_return(s, -EINVAL);
         assert_return(pid, -EINVAL);
         assert_return(s->type == SOURCE_CHILD, -EDOM);
@@ -1277,7 +1304,7 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         return 0;
 }
 
         return 0;
 }
 
-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);
@@ -1309,7 +1336,7 @@ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callbac
         return 0;
 }
 
         return 0;
 }
 
-void* sd_event_source_get_userdata(sd_event_source *s) {
+_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
         assert_return(s, NULL);
 
         return s->userdata;
         assert_return(s, NULL);
 
         return s->userdata;
@@ -1337,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;
@@ -1386,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;
 
@@ -1430,15 +1471,6 @@ static int process_io(sd_event *e, sd_event_source *s, uint32_t events) {
 
         s->io.revents = events;
 
 
         s->io.revents = events;
 
-        /*
-           If this is a oneshot event source, then we added it to the
-           epoll with EPOLLONESHOT, hence we know it's not registered
-           anymore. We can save a syscall here...
-        */
-
-        if (s->enabled == SD_EVENT_ONESHOT)
-                s->io.registered = false;
-
         return source_set_pending(s, true);
 }
 
         return source_set_pending(s, true);
 }
 
@@ -1594,7 +1626,7 @@ static int process_signal(sd_event *e, uint32_t events) {
 }
 
 static int source_dispatch(sd_event_source *s) {
 }
 
 static int source_dispatch(sd_event_source *s) {
-        int r;
+        int r = 0;
 
         assert(s);
         assert(s->pending || s->type == SOURCE_QUIT);
 
         assert(s);
         assert(s->pending || s->type == SOURCE_QUIT);
@@ -1611,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:
@@ -1642,6 +1676,8 @@ static int source_dispatch(sd_event_source *s) {
                 break;
         }
 
                 break;
         }
 
+        sd_event_source_unref(s);
+
         return r;
 }
 
         return r;
 }
 
@@ -1711,7 +1747,7 @@ static sd_event_source* event_next_pending(sd_event *e) {
         return p;
 }
 
         return p;
 }
 
-int sd_event_run(sd_event *e, uint64_t timeout) {
+_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         struct epoll_event ev_queue[EPOLL_QUEUE_MAX];
         sd_event_source *p;
         int r, i, m;
         struct epoll_event ev_queue[EPOLL_QUEUE_MAX];
         sd_event_source *p;
         int r, i, m;
@@ -1732,18 +1768,16 @@ 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));
@@ -1798,7 +1832,7 @@ finish:
         return r;
 }
 
         return r;
 }
 
-int sd_event_loop(sd_event *e) {
+_public_ int sd_event_loop(sd_event *e) {
         int r;
 
         assert_return(e, -EINVAL);
         int r;
 
         assert_return(e, -EINVAL);
@@ -1820,21 +1854,21 @@ finish:
         return r;
 }
 
         return r;
 }
 
-int sd_event_get_state(sd_event *e) {
+_public_ int sd_event_get_state(sd_event *e) {
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
 
         return e->state;
 }
 
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
 
         return e->state;
 }
 
-int sd_event_get_quit(sd_event *e) {
+_public_ int sd_event_get_quit(sd_event *e) {
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
 
         return e->quit_requested;
 }
 
         assert_return(e, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
 
         return e->quit_requested;
 }
 
-int sd_event_request_quit(sd_event *e) {
+_public_ int sd_event_request_quit(sd_event *e) {
         assert_return(e, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
         assert_return(e, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
@@ -1843,7 +1877,7 @@ int sd_event_request_quit(sd_event *e) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
+_public_ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
@@ -1853,7 +1887,7 @@ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
         return 0;
 }
 
         return 0;
 }
 
-int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
+_public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
@@ -1862,3 +1896,42 @@ 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;
+}