diff options
-rw-r--r-- | src/libsystemd/sd-event/sd-event.c | 72 | ||||
-rw-r--r-- | src/systemd/sd-event.h | 1 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 1f039bc37b..253923d8fa 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; @@ -97,6 +99,9 @@ struct sd_event_source { } defer; struct { sd_event_handler_t callback; + } post; + struct { + sd_event_handler_t callback; unsigned prioq_index; } exit; }; @@ -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 68c52c5145..45c36086f6 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); |