mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-08 20:58:20 +03:00
Merge pull request #17435 from poettering/event-shuffle-refactor
sd-event: split up sd_event_source_set_enable() function
This commit is contained in:
commit
23b13549fa
@ -701,6 +701,33 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig)
|
||||
event_unmask_signal_data(e, d, sig);
|
||||
}
|
||||
|
||||
static void event_source_pp_prioq_reshuffle(sd_event_source *s) {
|
||||
assert(s);
|
||||
|
||||
/* Reshuffles the pending + prepare prioqs. Called whenever the dispatch order changes, i.e. when
|
||||
* they are enabled/disabled or marked pending and such. */
|
||||
|
||||
if (s->pending)
|
||||
prioq_reshuffle(s->event->pending, s, &s->pending_index);
|
||||
|
||||
if (s->prepare)
|
||||
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
|
||||
}
|
||||
|
||||
static void event_source_time_prioq_reshuffle(sd_event_source *s) {
|
||||
struct clock_data *d;
|
||||
|
||||
assert(s);
|
||||
assert(EVENT_SOURCE_IS_TIME(s->type));
|
||||
|
||||
/* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy,
|
||||
* pending, enable state. Makes sure the two prioq's are ordered properly again. */
|
||||
assert_se(d = event_get_clock_data(s->event, s->type));
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
}
|
||||
|
||||
static void source_disconnect(sd_event_source *s) {
|
||||
sd_event *event;
|
||||
|
||||
@ -907,16 +934,8 @@ static int source_set_pending(sd_event_source *s, bool b) {
|
||||
} else
|
||||
assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
|
||||
|
||||
if (EVENT_SOURCE_IS_TIME(s->type)) {
|
||||
struct clock_data *d;
|
||||
|
||||
d = event_get_clock_data(s->event, s->type);
|
||||
assert(d);
|
||||
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
}
|
||||
if (EVENT_SOURCE_IS_TIME(s->type))
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
|
||||
if (s->type == SOURCE_SIGNAL && !b) {
|
||||
struct signal_data *d;
|
||||
@ -2207,11 +2226,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
|
||||
} else
|
||||
s->priority = priority;
|
||||
|
||||
if (s->pending)
|
||||
prioq_reshuffle(s->event->pending, s, &s->pending_index);
|
||||
|
||||
if (s->prepare)
|
||||
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
|
||||
event_source_pp_prioq_reshuffle(s);
|
||||
|
||||
if (s->type == SOURCE_EXIT)
|
||||
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
|
||||
@ -2237,6 +2252,152 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
|
||||
return s->enabled != SD_EVENT_OFF;
|
||||
}
|
||||
|
||||
static int event_source_disable(sd_event_source *s) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(s->enabled != SD_EVENT_OFF);
|
||||
|
||||
/* Unset the pending flag when this event source is disabled */
|
||||
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
|
||||
r = source_set_pending(s, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
|
||||
switch (s->type) {
|
||||
|
||||
case SOURCE_IO:
|
||||
source_io_unregister(s);
|
||||
break;
|
||||
|
||||
case SOURCE_TIME_REALTIME:
|
||||
case SOURCE_TIME_BOOTTIME:
|
||||
case SOURCE_TIME_MONOTONIC:
|
||||
case SOURCE_TIME_REALTIME_ALARM:
|
||||
case SOURCE_TIME_BOOTTIME_ALARM:
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
break;
|
||||
|
||||
case SOURCE_SIGNAL:
|
||||
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
|
||||
break;
|
||||
|
||||
case SOURCE_CHILD:
|
||||
assert(s->event->n_enabled_child_sources > 0);
|
||||
s->event->n_enabled_child_sources--;
|
||||
|
||||
if (EVENT_SOURCE_WATCH_PIDFD(s))
|
||||
source_child_pidfd_unregister(s);
|
||||
else
|
||||
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
|
||||
break;
|
||||
|
||||
case SOURCE_EXIT:
|
||||
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
|
||||
break;
|
||||
|
||||
case SOURCE_DEFER:
|
||||
case SOURCE_POST:
|
||||
case SOURCE_INOTIFY:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Wut? I shouldn't exist.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int event_source_enable(sd_event_source *s, int m) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(IN_SET(m, SD_EVENT_ON, SD_EVENT_ONESHOT));
|
||||
assert(s->enabled == SD_EVENT_OFF);
|
||||
|
||||
/* Unset the pending flag when this event source is enabled */
|
||||
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
|
||||
r = source_set_pending(s, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
s->enabled = m;
|
||||
|
||||
switch (s->type) {
|
||||
|
||||
case SOURCE_IO:
|
||||
r = source_io_register(s, m, s->io.events);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_TIME_REALTIME:
|
||||
case SOURCE_TIME_BOOTTIME:
|
||||
case SOURCE_TIME_MONOTONIC:
|
||||
case SOURCE_TIME_REALTIME_ALARM:
|
||||
case SOURCE_TIME_BOOTTIME_ALARM:
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
break;
|
||||
|
||||
case SOURCE_SIGNAL:
|
||||
r = event_make_signal_data(s->event, s->signal.sig, NULL);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_CHILD:
|
||||
s->event->n_enabled_child_sources++;
|
||||
|
||||
if (EVENT_SOURCE_WATCH_PIDFD(s)) {
|
||||
/* yes, we have pidfd */
|
||||
|
||||
r = source_child_pidfd_register(s, s->enabled);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
s->event->n_enabled_child_sources--;
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
/* no pidfd, or something other to watch for than WEXITED */
|
||||
|
||||
r = event_make_signal_data(s->event, SIGCHLD, NULL);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
s->event->n_enabled_child_sources--;
|
||||
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_EXIT:
|
||||
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
|
||||
break;
|
||||
|
||||
case SOURCE_DEFER:
|
||||
case SOURCE_POST:
|
||||
case SOURCE_INOTIFY:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Wut? I shouldn't exist.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
|
||||
int r;
|
||||
|
||||
@ -2244,182 +2405,29 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
|
||||
assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
|
||||
assert_return(!event_pid_changed(s->event), -ECHILD);
|
||||
|
||||
/* If we are dead anyway, we are fine with turning off
|
||||
* sources, but everything else needs to fail. */
|
||||
/* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */
|
||||
if (s->event->state == SD_EVENT_FINISHED)
|
||||
return m == SD_EVENT_OFF ? 0 : -ESTALE;
|
||||
|
||||
if (s->enabled == m)
|
||||
if (s->enabled == m) /* No change? */
|
||||
return 0;
|
||||
|
||||
if (m == SD_EVENT_OFF) {
|
||||
|
||||
/* Unset the pending flag when this event source is disabled */
|
||||
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
|
||||
r = source_set_pending(s, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (m == SD_EVENT_OFF)
|
||||
r = event_source_disable(s);
|
||||
else {
|
||||
if (s->enabled != SD_EVENT_OFF) {
|
||||
/* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the
|
||||
* event source is already enabled after all. */
|
||||
s->enabled = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (s->type) {
|
||||
|
||||
case SOURCE_IO:
|
||||
source_io_unregister(s);
|
||||
s->enabled = m;
|
||||
break;
|
||||
|
||||
case SOURCE_TIME_REALTIME:
|
||||
case SOURCE_TIME_BOOTTIME:
|
||||
case SOURCE_TIME_MONOTONIC:
|
||||
case SOURCE_TIME_REALTIME_ALARM:
|
||||
case SOURCE_TIME_BOOTTIME_ALARM: {
|
||||
struct clock_data *d;
|
||||
|
||||
s->enabled = m;
|
||||
d = event_get_clock_data(s->event, s->type);
|
||||
assert(d);
|
||||
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SOURCE_SIGNAL:
|
||||
s->enabled = m;
|
||||
|
||||
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
|
||||
break;
|
||||
|
||||
case SOURCE_CHILD:
|
||||
s->enabled = m;
|
||||
|
||||
assert(s->event->n_enabled_child_sources > 0);
|
||||
s->event->n_enabled_child_sources--;
|
||||
|
||||
if (EVENT_SOURCE_WATCH_PIDFD(s))
|
||||
source_child_pidfd_unregister(s);
|
||||
else
|
||||
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_EXIT:
|
||||
s->enabled = m;
|
||||
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
|
||||
break;
|
||||
|
||||
case SOURCE_DEFER:
|
||||
case SOURCE_POST:
|
||||
case SOURCE_INOTIFY:
|
||||
s->enabled = m;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Wut? I shouldn't exist.");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Unset the pending flag when this event source is enabled */
|
||||
if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
|
||||
r = source_set_pending(s, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
switch (s->type) {
|
||||
|
||||
case SOURCE_IO:
|
||||
r = source_io_register(s, m, s->io.events);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
s->enabled = m;
|
||||
break;
|
||||
|
||||
case SOURCE_TIME_REALTIME:
|
||||
case SOURCE_TIME_BOOTTIME:
|
||||
case SOURCE_TIME_MONOTONIC:
|
||||
case SOURCE_TIME_REALTIME_ALARM:
|
||||
case SOURCE_TIME_BOOTTIME_ALARM: {
|
||||
struct clock_data *d;
|
||||
|
||||
s->enabled = m;
|
||||
d = event_get_clock_data(s->event, s->type);
|
||||
assert(d);
|
||||
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SOURCE_SIGNAL:
|
||||
|
||||
s->enabled = m;
|
||||
|
||||
r = event_make_signal_data(s->event, s->signal.sig, NULL);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_CHILD:
|
||||
|
||||
if (s->enabled == SD_EVENT_OFF)
|
||||
s->event->n_enabled_child_sources++;
|
||||
|
||||
s->enabled = m;
|
||||
|
||||
if (EVENT_SOURCE_WATCH_PIDFD(s)) {
|
||||
/* yes, we have pidfd */
|
||||
|
||||
r = source_child_pidfd_register(s, s->enabled);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
s->event->n_enabled_child_sources--;
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
/* no pidfd, or something other to watch for than WEXITED */
|
||||
|
||||
r = event_make_signal_data(s->event, SIGCHLD, NULL);
|
||||
if (r < 0) {
|
||||
s->enabled = SD_EVENT_OFF;
|
||||
s->event->n_enabled_child_sources--;
|
||||
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOURCE_EXIT:
|
||||
s->enabled = m;
|
||||
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
|
||||
break;
|
||||
|
||||
case SOURCE_DEFER:
|
||||
case SOURCE_POST:
|
||||
case SOURCE_INOTIFY:
|
||||
s->enabled = m;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Wut? I shouldn't exist.");
|
||||
}
|
||||
r = event_source_enable(s, m);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (s->pending)
|
||||
prioq_reshuffle(s->event->pending, s, &s->pending_index);
|
||||
|
||||
if (s->prepare)
|
||||
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
|
||||
|
||||
event_source_pp_prioq_reshuffle(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2434,7 +2442,6 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
|
||||
}
|
||||
|
||||
_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
|
||||
struct clock_data *d;
|
||||
int r;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
@ -2448,13 +2455,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
|
||||
|
||||
s->time.next = usec;
|
||||
|
||||
d = event_get_clock_data(s->event, s->type);
|
||||
assert(d);
|
||||
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2486,7 +2487,6 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
|
||||
}
|
||||
|
||||
_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
|
||||
struct clock_data *d;
|
||||
int r;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
@ -2504,12 +2504,7 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
|
||||
|
||||
s->time.accuracy = usec;
|
||||
|
||||
d = event_get_clock_data(s->event, s->type);
|
||||
assert(d);
|
||||
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2888,9 +2883,7 @@ static int process_timer(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
|
||||
prioq_reshuffle(d->latest, s, &s->time.latest_index);
|
||||
d->needs_rearm = true;
|
||||
event_source_time_prioq_reshuffle(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user