chiark / gitweb /
core: dispatch run queue only if there's nothing else to do
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Nov 2013 14:22:41 +0000 (15:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 25 Nov 2013 16:40:53 +0000 (17:40 +0100)
Always read all external events before we decide what we do next.

src/core/job.c
src/core/manager.c
src/core/manager.h

index f791299a9d640755379435a222fa78f6a9d48862..9cd6ce24b8ff13d86ed8cfa086f7f31af2f8ffce 100644 (file)
@@ -874,6 +874,9 @@ void job_add_to_run_queue(Job *j) {
         if (j->in_run_queue)
                 return;
 
+        if (!j->manager->run_queue)
+                sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
+
         LIST_PREPEND(run_queue, j->manager->run_queue, j);
         j->in_run_queue = true;
 }
index b50182bce53c6bfa039f5032bfc1857aecd043f2..c424fece52f385170264f3eae032c58fc1d3de17 100644 (file)
@@ -95,6 +95,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
 static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
+static int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
 
 static int manager_setup_notify(Manager *m) {
         union {
@@ -456,6 +457,18 @@ int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
         if (r < 0)
                 goto fail;
 
+        r = sd_event_add_defer(m->event, manager_dispatch_run_queue, m, &m->run_queue_event_source);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(m->run_queue_event_source, SD_EVENT_PRIORITY_IDLE);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_OFF);
+        if (r < 0)
+                goto fail;
+
         r = manager_setup_signals(m);
         if (r < 0)
                 goto fail;
@@ -662,6 +675,7 @@ void manager_free(Manager *m) {
         sd_event_source_unref(m->time_change_event_source);
         sd_event_source_unref(m->jobs_in_progress_event_source);
         sd_event_source_unref(m->idle_pipe_event_source);
+        sd_event_source_unref(m->run_queue_event_source);
 
         if (m->signal_fd >= 0)
                 close_nointr_nofail(m->signal_fd);
@@ -1119,32 +1133,27 @@ void manager_clear_jobs(Manager *m) {
                 job_finish_and_invalidate(j, JOB_CANCELED, false);
 }
 
-static unsigned manager_dispatch_run_queue(Manager *m) {
+static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
+        Manager *m = userdata;
         Job *j;
-        unsigned n = 0;
-
-        if (m->dispatching_run_queue)
-                return 0;
 
-        m->dispatching_run_queue = true;
+        assert(source);
+        assert(m);
 
         while ((j = m->run_queue)) {
                 assert(j->installed);
                 assert(j->in_run_queue);
 
                 job_run_and_invalidate(j);
-                n++;
         }
 
-        m->dispatching_run_queue = false;
-
         if (m->n_running_jobs > 0)
                 manager_watch_jobs_in_progress(m);
 
         if (m->n_on_console > 0)
                 manager_watch_idle_pipe(m);
 
-        return n;
+        return 1;
 }
 
 static unsigned manager_dispatch_dbus_queue(Manager *m) {
@@ -1679,9 +1688,6 @@ int manager_loop(Manager *m) {
                 if (manager_dispatch_cgroup_queue(m) > 0)
                         continue;
 
-                if (manager_dispatch_run_queue(m) > 0)
-                        continue;
-
                 if (manager_dispatch_dbus_queue(m) > 0)
                         continue;
 
index 9eddef20dc1165401f886384678c0a77a97fcdb8..a46b09eddd8af068922208aaf805291055186758 100644 (file)
@@ -97,6 +97,8 @@ struct Manager {
 
         Hashmap *watch_pids;  /* pid => Unit object n:1 */
 
+        sd_event_source *run_queue_event_source;
+
         char *notify_socket;
         int notify_fd;
         sd_event_source *notify_event_source;
@@ -192,7 +194,6 @@ struct Manager {
         ManagerExitCode exit_code:5;
 
         bool dispatching_load_queue:1;
-        bool dispatching_run_queue:1;
         bool dispatching_dbus_queue:1;
 
         bool taint_usr:1;