diff --git a/src/core/job.c b/src/core/job.c index f791299a9d..9cd6ce24b8 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -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; } diff --git a/src/core/manager.c b/src/core/manager.c index b50182bce5..c424fece52 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -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; diff --git a/src/core/manager.h b/src/core/manager.h index 9eddef20dc..a46b09eddd 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -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;