#include "util.h"
#include "time-util.h"
#include "missing.h"
+#include "set.h"
#include "sd-event.h"
SOURCE_SIGNAL,
SOURCE_CHILD,
SOURCE_DEFER,
+ SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG
} EventSourceType;
struct {
sd_event_handler_t callback;
} defer;
+ struct {
+ sd_event_handler_t callback;
+ } post;
struct {
sd_event_handler_t callback;
unsigned prioq_index;
Hashmap *child_sources;
unsigned n_enabled_child_sources;
+ Set *post_sources;
+
Prioq *exit;
pid_t original_pid;
free(e->signal_sources);
hashmap_free(e->child_sources);
+ set_free(e->post_sources);
free(e);
}
/* 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;
_public_ int sd_event_add_io(
sd_event *e,
+ sd_event_source **ret,
int fd,
uint32_t events,
sd_event_io_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
int r;
static int event_add_time_internal(
sd_event *e,
+ sd_event_source **ret,
EventSourceType type,
int *timer_fd,
clockid_t id,
uint64_t usec,
uint64_t accuracy,
sd_event_time_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
int r;
}
_public_ int sd_event_add_monotonic(sd_event *e,
+ sd_event_source **ret,
uint64_t usec,
uint64_t accuracy,
sd_event_time_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
- return event_add_time_internal(e, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
+ return event_add_time_internal(e, ret, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata);
}
_public_ int sd_event_add_realtime(sd_event *e,
+ sd_event_source **ret,
uint64_t usec,
uint64_t accuracy,
sd_event_time_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
- return event_add_time_internal(e, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
+ return event_add_time_internal(e, ret, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->realtime_latest, usec, accuracy, callback, userdata);
}
static int event_update_signal_fd(sd_event *e) {
_public_ int sd_event_add_signal(
sd_event *e,
+ sd_event_source **ret,
int sig,
sd_event_signal_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
sigset_t ss;
_public_ int sd_event_add_child(
sd_event *e,
+ sd_event_source **ret,
pid_t pid,
int options,
sd_event_child_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
int r;
_public_ int sd_event_add_defer(
sd_event *e,
+ sd_event_source **ret,
sd_event_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
int r;
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,
sd_event_handler_t callback,
- void *userdata,
- sd_event_source **ret) {
+ void *userdata) {
sd_event_source *s;
int r;
break;
case SOURCE_DEFER:
+ case SOURCE_POST:
s->enabled = m;
break;
break;
case SOURCE_DEFER:
+ case SOURCE_POST:
s->enabled = m;
break;
if (r < 0)
return r;
}
-
- return 0;
}
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)
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;