b677e7
From d7ad6ad123200f562081ff09f7bed3c6d969ac0a Mon Sep 17 00:00:00 2001
b677e7
From: Lennart Poettering <lennart@poettering.net>
b677e7
Date: Fri, 23 Oct 2020 21:21:58 +0200
b677e7
Subject: [PATCH] sd-event: split out enable and disable codepaths from
b677e7
 sd_event_source_set_enabled()
b677e7
MIME-Version: 1.0
b677e7
Content-Type: text/plain; charset=UTF-8
b677e7
Content-Transfer-Encoding: 8bit
b677e7
b677e7
So far half of sd_event_source_set_enabled() was doing enabling, the
b677e7
other half was doing disabling. Let's split that into two separate
b677e7
calls.
b677e7
b677e7
(This also adds a new shortcut to sd_event_source_set_enabled(): if the
b677e7
caller toggles between "ON" and "ONESHOT" we'll now shortcut this, since
b677e7
the event source is already enabled in that case and shall remain
b677e7
enabled.)
b677e7
b677e7
This heavily borrows and is inspired from Michal Sekletár's #17284
b677e7
refactoring.
b677e7
b677e7
(cherry picked from commit ddfde737b546c17e54182028153aa7f7e78804e3)
b677e7
b677e7
Related: #1819868
b677e7
---
b677e7
 src/libsystemd/sd-event/sd-event.c | 227 +++++++++++++++--------------
b677e7
 1 file changed, 121 insertions(+), 106 deletions(-)
b677e7
b677e7
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
b677e7
index 47f99eb096..df5ed0dce8 100644
b677e7
--- a/src/libsystemd/sd-event/sd-event.c
b677e7
+++ b/src/libsystemd/sd-event/sd-event.c
b677e7
@@ -2260,152 +2260,167 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
b677e7
         return 0;
b677e7
 }
b677e7
 
b677e7
-_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
b677e7
+static int event_source_disable(sd_event_source *s) {
b677e7
         int r;
b677e7
 
b677e7
-        assert_return(s, -EINVAL);
b677e7
-        assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
b677e7
-        assert_return(!event_pid_changed(s->event), -ECHILD);
b677e7
+        assert(s);
b677e7
+        assert(s->enabled != SD_EVENT_OFF);
b677e7
 
b677e7
-        /* If we are dead anyway, we are fine with turning off
b677e7
-         * sources, but everything else needs to fail. */
b677e7
-        if (s->event->state == SD_EVENT_FINISHED)
b677e7
-                return m == SD_EVENT_OFF ? 0 : -ESTALE;
b677e7
+        /* Unset the pending flag when this event source is disabled */
b677e7
+        if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
b677e7
+                r = source_set_pending(s, false);
b677e7
+                if (r < 0)
b677e7
+                        return r;
b677e7
+        }
b677e7
 
b677e7
-        if (s->enabled == m)
b677e7
-                return 0;
b677e7
+        s->enabled = SD_EVENT_OFF;
b677e7
 
b677e7
-        if (m == SD_EVENT_OFF) {
b677e7
+        switch (s->type) {
b677e7
 
b677e7
-                /* Unset the pending flag when this event source is disabled */
b677e7
-                if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
b677e7
-                        r = source_set_pending(s, false);
b677e7
-                        if (r < 0)
b677e7
-                                return r;
b677e7
-                }
b677e7
+        case SOURCE_IO:
b677e7
+                source_io_unregister(s);
b677e7
+                break;
b677e7
 
b677e7
-                switch (s->type) {
b677e7
+        case SOURCE_TIME_REALTIME:
b677e7
+        case SOURCE_TIME_BOOTTIME:
b677e7
+        case SOURCE_TIME_MONOTONIC:
b677e7
+        case SOURCE_TIME_REALTIME_ALARM:
b677e7
+        case SOURCE_TIME_BOOTTIME_ALARM:
b677e7
+                event_source_time_prioq_reshuffle(s);
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_IO:
b677e7
-                        source_io_unregister(s);
b677e7
-                        s->enabled = m;
b677e7
-                        break;
b677e7
+        case SOURCE_SIGNAL:
b677e7
+                event_gc_signal_data(s->event, &s->priority, s->signal.sig);
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_TIME_REALTIME:
b677e7
-                case SOURCE_TIME_BOOTTIME:
b677e7
-                case SOURCE_TIME_MONOTONIC:
b677e7
-                case SOURCE_TIME_REALTIME_ALARM:
b677e7
-                case SOURCE_TIME_BOOTTIME_ALARM:
b677e7
-                        s->enabled = m;
b677e7
-                        event_source_time_prioq_reshuffle(s);
b677e7
-                        break;
b677e7
+        case SOURCE_CHILD:
b677e7
+                assert(s->event->n_enabled_child_sources > 0);
b677e7
+                s->event->n_enabled_child_sources--;
b677e7
 
b677e7
-                case SOURCE_SIGNAL:
b677e7
-                        s->enabled = m;
b677e7
+                event_gc_signal_data(s->event, &s->priority, SIGCHLD);
b677e7
+                break;
b677e7
 
b677e7
-                        event_gc_signal_data(s->event, &s->priority, s->signal.sig);
b677e7
-                        break;
b677e7
+        case SOURCE_EXIT:
b677e7
+                prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_CHILD:
b677e7
-                        s->enabled = m;
b677e7
+        case SOURCE_DEFER:
b677e7
+        case SOURCE_POST:
b677e7
+        case SOURCE_INOTIFY:
b677e7
+                break;
b677e7
 
b677e7
-                        assert(s->event->n_enabled_child_sources > 0);
b677e7
-                        s->event->n_enabled_child_sources--;
b677e7
+        default:
b677e7
+                assert_not_reached("Wut? I shouldn't exist.");
b677e7
+        }
b677e7
 
b677e7
-                        event_gc_signal_data(s->event, &s->priority, SIGCHLD);
b677e7
-                        break;
b677e7
+        return 0;
b677e7
+}
b677e7
 
b677e7
-                case SOURCE_EXIT:
b677e7
-                        s->enabled = m;
b677e7
-                        prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
b677e7
-                        break;
b677e7
+static int event_source_enable(sd_event_source *s, int m) {
b677e7
+        int r;
b677e7
 
b677e7
-                case SOURCE_DEFER:
b677e7
-                case SOURCE_POST:
b677e7
-                case SOURCE_INOTIFY:
b677e7
-                        s->enabled = m;
b677e7
-                        break;
b677e7
+        assert(s);
b677e7
+        assert(IN_SET(m, SD_EVENT_ON, SD_EVENT_ONESHOT));
b677e7
+        assert(s->enabled == SD_EVENT_OFF);
b677e7
 
b677e7
-                default:
b677e7
-                        assert_not_reached("Wut? I shouldn't exist.");
b677e7
-                }
b677e7
+        /* Unset the pending flag when this event source is enabled */
b677e7
+        if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
b677e7
+                r = source_set_pending(s, false);
b677e7
+                if (r < 0)
b677e7
+                        return r;
b677e7
+        }
b677e7
 
b677e7
-        } else {
b677e7
+        s->enabled = m;
b677e7
 
b677e7
-                /* Unset the pending flag when this event source is enabled */
b677e7
-                if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
b677e7
-                        r = source_set_pending(s, false);
b677e7
-                        if (r < 0)
b677e7
-                                return r;
b677e7
+        switch (s->type) {
b677e7
+
b677e7
+        case SOURCE_IO:
b677e7
+                r = source_io_register(s, m, s->io.events);
b677e7
+                if (r < 0) {
b677e7
+                        s->enabled = SD_EVENT_OFF;
b677e7
+                        return r;
b677e7
                 }
b677e7
 
b677e7
-                switch (s->type) {
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_IO:
b677e7
-                        r = source_io_register(s, m, s->io.events);
b677e7
-                        if (r < 0)
b677e7
-                                return r;
b677e7
+        case SOURCE_TIME_REALTIME:
b677e7
+        case SOURCE_TIME_BOOTTIME:
b677e7
+        case SOURCE_TIME_MONOTONIC:
b677e7
+        case SOURCE_TIME_REALTIME_ALARM:
b677e7
+        case SOURCE_TIME_BOOTTIME_ALARM:
b677e7
+                event_source_time_prioq_reshuffle(s);
b677e7
+                break;
b677e7
 
b677e7
-                        s->enabled = m;
b677e7
-                        break;
b677e7
+        case SOURCE_SIGNAL:
b677e7
+                r = event_make_signal_data(s->event, s->signal.sig, NULL);
b677e7
+                if (r < 0) {
b677e7
+                        s->enabled = SD_EVENT_OFF;
b677e7
+                        event_gc_signal_data(s->event, &s->priority, s->signal.sig);
b677e7
+                        return r;
b677e7
+                }
b677e7
 
b677e7
-                case SOURCE_TIME_REALTIME:
b677e7
-                case SOURCE_TIME_BOOTTIME:
b677e7
-                case SOURCE_TIME_MONOTONIC:
b677e7
-                case SOURCE_TIME_REALTIME_ALARM:
b677e7
-                case SOURCE_TIME_BOOTTIME_ALARM:
b677e7
-                        s->enabled = m;
b677e7
-                        event_source_time_prioq_reshuffle(s);
b677e7
-                        break;
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_SIGNAL:
b677e7
+        case SOURCE_CHILD:
b677e7
+                s->event->n_enabled_child_sources++;
b677e7
 
b677e7
-                        s->enabled = m;
b677e7
+                r = event_make_signal_data(s->event, SIGCHLD, NULL);
b677e7
+                if (r < 0) {
b677e7
+                        s->enabled = SD_EVENT_OFF;
b677e7
+                        s->event->n_enabled_child_sources--;
b677e7
+                        event_gc_signal_data(s->event, &s->priority, SIGCHLD);
b677e7
+                        return r;
b677e7
+                }
b677e7
 
b677e7
-                        r = event_make_signal_data(s->event, s->signal.sig, NULL);
b677e7
-                        if (r < 0) {
b677e7
-                                s->enabled = SD_EVENT_OFF;
b677e7
-                                event_gc_signal_data(s->event, &s->priority, s->signal.sig);
b677e7
-                                return r;
b677e7
-                        }
b677e7
 
b677e7
-                        break;
b677e7
+                break;
b677e7
 
b677e7
-                case SOURCE_CHILD:
b677e7
+        case SOURCE_EXIT:
b677e7
+                prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
b677e7
+                break;
b677e7
 
b677e7
-                        if (s->enabled == SD_EVENT_OFF)
b677e7
-                                s->event->n_enabled_child_sources++;
b677e7
+        case SOURCE_DEFER:
b677e7
+        case SOURCE_POST:
b677e7
+        case SOURCE_INOTIFY:
b677e7
+                break;
b677e7
 
b677e7
-                        s->enabled = m;
b677e7
+        default:
b677e7
+                assert_not_reached("Wut? I shouldn't exist.");
b677e7
+        }
b677e7
 
b677e7
-                        r = event_make_signal_data(s->event, SIGCHLD, NULL);
b677e7
-                        if (r < 0) {
b677e7
-                                s->enabled = SD_EVENT_OFF;
b677e7
-                                s->event->n_enabled_child_sources--;
b677e7
-                                event_gc_signal_data(s->event, &s->priority, SIGCHLD);
b677e7
-                                return r;
b677e7
-                        }
b677e7
+        return 0;
b677e7
+}
b677e7
 
b677e7
-                        break;
b677e7
+_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
b677e7
+        int r;
b677e7
 
b677e7
-                case SOURCE_EXIT:
b677e7
-                        s->enabled = m;
b677e7
-                        prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
b677e7
-                        break;
b677e7
+        assert_return(s, -EINVAL);
b677e7
+        assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
b677e7
+        assert_return(!event_pid_changed(s->event), -ECHILD);
b677e7
 
b677e7
-                case SOURCE_DEFER:
b677e7
-                case SOURCE_POST:
b677e7
-                case SOURCE_INOTIFY:
b677e7
-                        s->enabled = m;
b677e7
-                        break;
b677e7
+        /* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */
b677e7
+        if (s->event->state == SD_EVENT_FINISHED)
b677e7
+                return m == SD_EVENT_OFF ? 0 : -ESTALE;
b677e7
 
b677e7
-                default:
b677e7
-                        assert_not_reached("Wut? I shouldn't exist.");
b677e7
+        if (s->enabled == m) /* No change? */
b677e7
+                return 0;
b677e7
+
b677e7
+        if (m == SD_EVENT_OFF)
b677e7
+                r = event_source_disable(s);
b677e7
+        else {
b677e7
+                if (s->enabled != SD_EVENT_OFF) {
b677e7
+                        /* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the
b677e7
+                         * event source is already enabled after all. */
b677e7
+                        s->enabled = m;
b677e7
+                        return 0;
b677e7
                 }
b677e7
+
b677e7
+                r = event_source_enable(s, m);
b677e7
         }
b677e7
+        if (r < 0)
b677e7
+                return r;
b677e7
 
b677e7
         event_source_pp_prioq_reshuffle(s);
b677e7
-
b677e7
         return 0;
b677e7
 }
b677e7