From 6e9feda30d6d5c4aa9908d458c92eb0daf90eb3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Feb 2014 21:06:09 +0100 Subject: [PATCH] event: add new kind of event source called "post" This new event source is triggered by the dispatching of any non-post event source. It can thus be used to do clean-up or recheck work, triggered by any other event source having been executed. This is different from "defer" event source which are unconditionally triggered as long as they are enabled. A "defer" event source that does nothing will result in the event loop busy looping unless it is turned off eventually. This is different for "post" event sources that will be only triggered when some other non-post ran, and will thus not keep the event loop busy on its own. --- src/libsystemd/sd-event/sd-event.c | 72 ++++++++++++++++++++++++++++++ src/systemd/sd-event.h | 1 + 2 files changed, 73 insertions(+) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 1f039bc37..253923d8f 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -32,6 +32,7 @@ #include "util.h" #include "time-util.h" #include "missing.h" +#include "set.h" #include "sd-event.h" @@ -45,6 +46,7 @@ typedef enum EventSourceType { SOURCE_SIGNAL, SOURCE_CHILD, SOURCE_DEFER, + SOURCE_POST, SOURCE_EXIT, SOURCE_WATCHDOG } EventSourceType; @@ -95,6 +97,9 @@ struct sd_event_source { struct { sd_event_handler_t callback; } defer; + struct { + sd_event_handler_t callback; + } post; struct { sd_event_handler_t callback; unsigned prioq_index; @@ -134,6 +139,8 @@ struct sd_event { Hashmap *child_sources; unsigned n_enabled_child_sources; + Set *post_sources; + Prioq *exit; pid_t original_pid; @@ -350,6 +357,7 @@ static void event_free(sd_event *e) { free(e->signal_sources); hashmap_free(e->child_sources); + set_free(e->post_sources); free(e); } @@ -524,6 +532,10 @@ static void source_free(sd_event_source *s) { /* nothing */ break; + case SOURCE_POST: + set_remove(s->event->post_sources, s); + break; + case SOURCE_EXIT: prioq_remove(s->event->exit, s, &s->exit.prioq_index); break; @@ -957,6 +969,43 @@ _public_ int sd_event_add_defer( return 0; } +_public_ int sd_event_add_post( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = set_ensure_allocated(&e->post_sources, trivial_hash_func, trivial_compare_func); + if (r < 0) + return r; + + s = source_new(e, SOURCE_POST); + if (!s) + return -ENOMEM; + + s->post.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + r = set_put(e->post_sources, s); + if (r < 0) { + source_free(s); + return r; + } + + *ret = s; + return 0; +} + _public_ int sd_event_add_exit( sd_event *e, sd_event_source **ret, @@ -1246,6 +1295,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { break; case SOURCE_DEFER: + case SOURCE_POST: s->enabled = m; break; @@ -1304,6 +1354,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { break; case SOURCE_DEFER: + case SOURCE_POST: s->enabled = m; break; @@ -1779,6 +1830,23 @@ static int source_dispatch(sd_event_source *s) { return r; } + if (s->type != SOURCE_POST) { + sd_event_source *z; + Iterator i; + + /* If we execute a non-post source, let's mark all + * post sources as pending */ + + SET_FOREACH(z, s->event->post_sources, i) { + if (z->enabled == SD_EVENT_OFF) + continue; + + r = source_set_pending(z, true); + if (r < 0) + return r; + } + } + if (s->enabled == SD_EVENT_ONESHOT) { r = sd_event_source_set_enabled(s, SD_EVENT_OFF); if (r < 0) @@ -1825,6 +1893,10 @@ static int source_dispatch(sd_event_source *s) { r = s->defer.callback(s, s->userdata); break; + case SOURCE_POST: + r = s->post.callback(s, s->userdata); + break; + case SOURCE_EXIT: r = s->exit.callback(s, s->userdata); break; diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h index 68c52c514..45c36086f 100644 --- a/src/systemd/sd-event.h +++ b/src/systemd/sd-event.h @@ -82,6 +82,7 @@ int sd_event_add_realtime(sd_event *e, sd_event_source **s, uint64_t usec, uint6 int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); +int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_run(sd_event *e, uint64_t timeout); -- 2.30.2