summaryrefslogtreecommitdiff
path: root/src/libsystemd
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-21 21:06:09 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-21 21:13:53 +0100
commit6e9feda30d6d5c4aa9908d458c92eb0daf90eb3a (patch)
tree11c80438fe5d8feca7256c9e605fbeceacdb0187 /src/libsystemd
parentd7c9a162f1e15cc21636b57ab7f45097446b932c (diff)
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.
Diffstat (limited to 'src/libsystemd')
-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;