chiark / gitweb /
event: clear pending-state when re-arming timers
[elogind.git] / src / libsystemd-bus / sd-event.c
index dd8d3ee..d01e82d 100644 (file)
 #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 "sd-id128.h"
+#include "missing.h"
 
 #include "sd-event.h"
 
@@ -138,6 +139,9 @@ struct sd_event {
 
         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) {
@@ -304,6 +308,9 @@ static int quit_prioq_compare(const void *a, const void *b) {
 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);
 
@@ -330,7 +337,7 @@ static void event_free(sd_event *e) {
         free(e);
 }
 
-int sd_event_new(sd_event** ret) {
+_public_ int sd_event_new(sd_event** ret) {
         sd_event *e;
         int r;
 
@@ -367,7 +374,7 @@ fail:
         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);
@@ -376,7 +383,7 @@ sd_event* sd_event_ref(sd_event *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);
@@ -556,7 +563,7 @@ static sd_event_source *source_new(sd_event *e, EventSourceType type) {
         return s;
 }
 
-int sd_event_add_io(
+_public_ int sd_event_add_io(
                 sd_event *e,
                 int fd,
                 uint32_t events,
@@ -712,11 +719,23 @@ fail:
         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_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);
 }
 
-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_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);
 }
 
@@ -752,7 +771,7 @@ static int event_update_signal_fd(sd_event *e) {
         return 0;
 }
 
-int sd_event_add_signal(
+_public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
                 sd_signal_handler_t callback,
@@ -801,7 +820,7 @@ int sd_event_add_signal(
         return 0;
 }
 
-int sd_event_add_child(
+_public_ int sd_event_add_child(
                 sd_event *e,
                 pid_t pid,
                 int options,
@@ -862,7 +881,7 @@ int sd_event_add_child(
         return 0;
 }
 
-int sd_event_add_defer(
+_public_ int sd_event_add_defer(
                 sd_event *e,
                 sd_defer_handler_t callback,
                 void *userdata,
@@ -895,7 +914,7 @@ int sd_event_add_defer(
         return 0;
 }
 
-int sd_event_add_quit(
+_public_ int sd_event_add_quit(
                 sd_event *e,
                 sd_quit_handler_t callback,
                 void *userdata,
@@ -935,7 +954,7 @@ int sd_event_add_quit(
         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);
@@ -944,7 +963,7 @@ sd_event_source* sd_event_source_ref(sd_event_source *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);
@@ -956,13 +975,13 @@ sd_event_source* sd_event_source_unref(sd_event_source *s) {
         return NULL;
 }
 
-sd_event *sd_event_get(sd_event_source *s) {
+_public_ sd_event *sd_event_get(sd_event_source *s) {
         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);
@@ -971,7 +990,7 @@ int sd_event_source_get_pending(sd_event_source *s) {
         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);
@@ -979,7 +998,7 @@ int sd_event_source_get_io_fd(sd_event_source *s) {
         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);
@@ -989,7 +1008,7 @@ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
         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);
@@ -1012,7 +1031,7 @@ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
         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);
@@ -1023,7 +1042,7 @@ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
         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);
@@ -1031,14 +1050,14 @@ int sd_event_source_get_signal(sd_event_source *s) {
         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;
 }
 
-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);
@@ -1060,7 +1079,7 @@ int sd_event_source_set_priority(sd_event_source *s, int priority) {
         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);
@@ -1069,7 +1088,7 @@ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
         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);
@@ -1201,7 +1220,7 @@ int sd_event_source_set_enabled(sd_event_source *s, int m) {
         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);
@@ -1211,7 +1230,7 @@ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
         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);
@@ -1222,6 +1241,7 @@ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
                 return 0;
 
         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);
@@ -1234,7 +1254,7 @@ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         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);
@@ -1244,7 +1264,7 @@ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
         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);
@@ -1267,7 +1287,7 @@ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
         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);
@@ -1277,7 +1297,7 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         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_prepare_handler_t callback) {
         int r;
 
         assert_return(s, -EINVAL);
@@ -1309,7 +1329,7 @@ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callbac
         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;
@@ -1430,15 +1450,6 @@ static int process_io(sd_event *e, sd_event_source *s, uint32_t 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);
 }
 
@@ -1594,7 +1605,7 @@ static int process_signal(sd_event *e, uint32_t events) {
 }
 
 static int source_dispatch(sd_event_source *s) {
-        int r;
+        int r = 0;
 
         assert(s);
         assert(s->pending || s->type == SOURCE_QUIT);
@@ -1611,6 +1622,8 @@ static int source_dispatch(sd_event_source *s) {
                         return r;
         }
 
+        sd_event_source_ref(s);
+
         switch (s->type) {
 
         case SOURCE_IO:
@@ -1642,6 +1655,8 @@ static int source_dispatch(sd_event_source *s) {
                 break;
         }
 
+        sd_event_source_unref(s);
+
         return r;
 }
 
@@ -1711,7 +1726,7 @@ static sd_event_source* event_next_pending(sd_event *e) {
         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;
@@ -1748,7 +1763,7 @@ int sd_event_run(sd_event *e, uint64_t timeout) {
         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));
         if (m < 0) {
-                r = m;
+                r = errno == EAGAIN || errno == EINTR ? 0 : -errno;
                 goto finish;
         }
 
@@ -1798,7 +1813,7 @@ finish:
         return r;
 }
 
-int sd_event_loop(sd_event *e) {
+_public_ int sd_event_loop(sd_event *e) {
         int r;
 
         assert_return(e, -EINVAL);
@@ -1820,21 +1835,21 @@ finish:
         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;
 }
 
-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;
 }
 
-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);
@@ -1843,7 +1858,7 @@ int sd_event_request_quit(sd_event *e) {
         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);
@@ -1853,7 +1868,7 @@ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
         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);
@@ -1862,3 +1877,42 @@ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
         *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;
+}