summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-event/sd-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-event/sd-event.c')
-rw-r--r--src/libsystemd/sd-event/sd-event.c72
1 files changed, 72 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;