]> git.tue.mpg.de Git - paraslash.git/commitdiff
sched: Allow more than one running scheduler instance.
authorAndre Noll <maan@systemlinux.org>
Fri, 2 Sep 2011 16:27:29 +0000 (18:27 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 20 Nov 2011 14:08:41 +0000 (15:08 +0100)
The interactive completion code must be able to run a second,
independent scheduler instance for generating the possible completions.
This is currently not possible because the pre_select and post_select
list heads of the scheduler are defined globally in sched.c.

This patch moves these list heads from sched.c to struct sched. This
leaves only the global "now" variable in sched.c, but it is OK to
update this from all scheduler instances, so it can stay.

Moving the two list heads to struct sched requires that several
public functions, among them register_task(), grow an additional
parameter. The (mostly trivial) changes that update all callers to
provide the new argument make the patch rather invasive, unfortunately.

23 files changed:
afs.c
audiod.c
audiod_command.c
client.c
client.h
client_common.c
command.c
dccp_send.c
filter.c
grab_client.c
grab_client.h
http_send.c
recv.c
sched.c
sched.h
send_common.c
server.c
udp_send.c
vss.c
vss.h
write.c
write_common.c
write_common.h

diff --git a/afs.c b/afs.c
index 3f3780519ab0ddddcba6ff876ead15324b9951ec..b4c85dcb82eb2061501c2567005f66015b30b6f0 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -727,11 +727,11 @@ static void afs_signal_post_select(struct sched *s, struct task *t)
        }
        PARA_EMERG_LOG("terminating on signal %d\n", signum);
 shutdown:
-       sched_shutdown();
+       sched_shutdown(s);
        t->error = -E_AFS_SIGNAL;
 }
 
-static void register_signal_task(void)
+static void register_signal_task(struct sched *s)
 {
        struct signal_task *st = &signal_task_struct;
 
@@ -745,7 +745,7 @@ static void register_signal_task(void)
        st->task.pre_select = signal_pre_select;
        st->task.post_select = afs_signal_post_select;
        sprintf(st->task.status, "signal task");
-       register_task(&st->task);
+       register_task(s, &st->task);
 }
 
 static struct list_head afs_client_list;
@@ -906,7 +906,7 @@ static void command_post_select(struct sched *s, struct task *t)
        ret = execute_server_command(&s->rfds);
        if (ret < 0) {
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-               sched_shutdown();
+               sched_shutdown(s);
                return;
        }
        /* Check the list of connected clients. */
@@ -941,7 +941,7 @@ static void command_post_select(struct sched *s, struct task *t)
        para_list_add(&client->node, &afs_client_list);
 }
 
-static void register_command_task(uint32_t cookie)
+static void register_command_task(uint32_t cookie, struct sched *s)
 {
        struct command_task *ct = &command_task_struct;
        ct->fd = setup_command_socket_or_die();
@@ -950,7 +950,7 @@ static void register_command_task(uint32_t cookie)
        ct->task.pre_select = command_pre_select;
        ct->task.post_select = command_post_select;
        sprintf(ct->task.status, "afs command task");
-       register_task(&ct->task);
+       register_task(s, &ct->task);
 }
 
 /**
@@ -964,7 +964,7 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd)
        static struct sched s;
        int i, ret;
 
-       register_signal_task();
+       register_signal_task(&s);
        INIT_LIST_HEAD(&afs_client_list);
        for (i = 0; i < NUM_AFS_TABLES; i++)
                afs_tables[i].init(&afs_tables[i]);
@@ -978,7 +978,7 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd)
        PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
                server_socket, (unsigned) cookie);
        init_admissible_files(conf.afs_initial_mode_arg);
-       register_command_task(cookie);
+       register_command_task(cookie, &s);
        s.default_timeout.tv_sec = 0;
        s.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&s);
index 7085ef0f4da3e303df923c4ea6dd1b705911968d..295787262ae66589ceb6dc2d56da258e77943ef8 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -78,6 +78,8 @@ enum vss_status_flags {
        VSS_STATUS_FLAG_PLAYING = 2,
 };
 
+struct sched sched = {.max_fileno = 0};
+
 /**
  * The task for obtaining para_server's status (para_client stat).
  *
@@ -505,7 +507,7 @@ static void open_filters(struct slot_info *s)
                                .handler = f->execute, .context = fn));
 
                f->open(fn);
-               register_task(&fn->task);
+               register_task(&sched, &fn->task);
                parent = fn->btrn;
                PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n",
                        audio_formats[s->format], i,  nf, f->name, (int)(s - slot));
@@ -528,7 +530,7 @@ static void open_writers(struct slot_info *s)
                wn = s->wns + i;
                wn->conf = a->writer_conf[i];
                wn->writer_num = a->writer_nums[i];
-               register_writer_node(wn, parent);
+               register_writer_node(wn, parent, &sched);
        }
 }
 
@@ -565,7 +567,7 @@ static int open_receiver(int format)
        rn->task.pre_select = r->pre_select;
        rn->task.post_select = r->post_select;
        sprintf(rn->task.status, "%s receiver node", r->name);
-       register_task(&rn->task);
+       register_task(&sched, &rn->task);
        return slot_num;
 }
 
@@ -1147,7 +1149,7 @@ static void start_stop_decoders(void)
        if (a->num_filters)
                open_filters(sl);
        open_writers(sl);
-       activate_grab_clients();
+       activate_grab_clients(&sched);
        btr_log_tree(sl->receiver_node->btrn, LL_NOTICE);
 }
 
@@ -1180,7 +1182,7 @@ min_delay:
 }
 
 /* restart the client task if necessary */
-static void status_post_select(__a_unused struct sched *s, struct task *t)
+static void status_post_select(struct sched *s, struct task *t)
 {
        struct status_task *st = container_of(t, struct status_task, task);
 
@@ -1242,13 +1244,13 @@ static void status_post_select(__a_unused struct sched *s, struct task *t)
                int argc = 5;
                PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
                st->clock_diff_count--;
-               client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+               client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
                set_stat_task_restart_barrier(2);
 
        } else {
                char *argv[] = {"audiod", "--", "stat", "-p", NULL};
                int argc = 4;
-               client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+               client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
                set_stat_task_restart_barrier(5);
        }
        free(stat_item_values[SI_BASENAME]);
@@ -1332,7 +1334,6 @@ static void init_colors_or_die(void)
 int main(int argc, char *argv[])
 {
        int ret, i;
-       static struct sched s;
        struct command_task command_task_struct, *cmd_task = &command_task_struct;
        struct audiod_cmdline_parser_params params = {
                .override = 0,
@@ -1384,12 +1385,12 @@ int main(int argc, char *argv[])
        if (conf.daemon_given)
                daemonize(false /* parent exits immediately */);
 
-       register_task(&sig_task->task);
-       register_task(&cmd_task->task);
-       register_task(&stat_task->task);
-       s.default_timeout.tv_sec = 2;
-       s.default_timeout.tv_usec = 999 * 1000;
-       ret = schedule(&s);
+       register_task(&sched, &sig_task->task);
+       register_task(&sched, &cmd_task->task);
+       register_task(&sched, &stat_task->task);
+       sched.default_timeout.tv_sec = 2;
+       sched.default_timeout.tv_usec = 999 * 1000;
+       ret = schedule(&sched);
 
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
        return EXIT_FAILURE;
index dfb014aebc1c1d12659364189ac79813c952139c..adfa07edfc6c603b936cb52df4615323b5d62bb0 100644 (file)
@@ -27,6 +27,7 @@
 #include "fd.h"
 #include "audiod_command_list.h"
 
+extern struct sched sched;
 extern char *stat_item_values[NUM_STAT_ITEMS];
 
 /** Iterate over the array of all audiod commands. */
@@ -286,7 +287,7 @@ out:
 
 int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
 {
-       char *tl = get_task_list();
+       char *tl = get_task_list(&sched);
        int ret = 1;
        if (tl)
                ret = client_write(fd, tl);
@@ -344,7 +345,7 @@ int com_stat(int fd, int argc, char **argv)
 
 int com_grab(int fd, int argc, char **argv)
 {
-       return grab_client_new(fd, argc, argv);
+       return grab_client_new(fd, argc, argv, &sched);
 }
 
 __noreturn int com_term(int fd, __a_unused int argc, __a_unused char **argv)
index b6a2f24157b7a01a63f9bbb13418c2c2326559dc..038fc0134e52adcc041fa52c152a321b9818b58e 100644 (file)
--- a/client.c
+++ b/client.c
 
 INIT_CLIENT_ERRLISTS;
 
+static struct sched sched;
 static struct client_task *ct;
 static struct stdin_task sit;
 static struct stdout_task sot;
 
-static void supervisor_post_select(__a_unused struct sched *s, struct task *t)
+static void supervisor_post_select(struct sched *s, struct task *t)
 {
        if (ct->task.error < 0) {
                t->error = ct->task.error;
@@ -35,13 +36,13 @@ static void supervisor_post_select(__a_unused struct sched *s, struct task *t)
        }
        if (ct->status == CL_SENDING) {
                stdin_set_defaults(&sit);
-               register_task(&sit.task);
+               register_task(s, &sit.task);
                t->error = -E_TASK_STARTED;
                return;
        }
        if (ct->status == CL_RECEIVING) {
                stdout_set_defaults(&sot);
-               register_task(&sot.task);
+               register_task(s, &sot.task);
                t->error = -E_TASK_STARTED;
                return;
        }
@@ -82,6 +83,7 @@ int main(int argc, char *argv[])
        init_random_seed_or_die();
        s.default_timeout.tv_sec = 1;
        s.default_timeout.tv_usec = 0;
+
        /*
         * We add buffer tree nodes for stdin and stdout even though
         * only one of them will be needed. This simplifies the code
@@ -89,13 +91,13 @@ int main(int argc, char *argv[])
         */
        sit.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdin"));
-       ret = client_open(argc, argv, &ct, &client_loglevel, sit.btrn, NULL);
+       ret = client_open(argc, argv, &ct, &client_loglevel, sit.btrn, NULL, &sched);
        if (ret < 0)
                goto out;
        sot.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdout", .parent = ct->btrn));
-       register_task(&svt);
-       ret = schedule(&s);
+       register_task(&sched, &svt);
+       ret = schedule(&sched);
 out:
        client_close(ct);
        btr_free_node(sit.btrn);
index 28b786a4ce091e132863a0076c6473b645dd60d2..3aa048ac8eb727946bb8df9fee1e727ffe52f1df 100644 (file)
--- a/client.h
+++ b/client.h
@@ -48,4 +48,5 @@ struct client_task {
 
 void client_close(struct client_task *ct);
 int client_open(int argc, char *argv[], struct client_task **ct_ptr,
-               int *loglevel, struct btr_node *parent, struct btr_node *child);
+               int *loglevel, struct btr_node *parent, struct btr_node *child,
+               struct sched *sched);
index eb9f9e1fcda2a49ba960582ba67be9c882897a20..85978c8ea24db5e5c0f90610e8feb77851eb6739 100644 (file)
@@ -310,7 +310,7 @@ out:
 }
 
 /* connect to para_server and register the client task */
-static int client_connect(struct client_task *ct)
+static int client_connect(struct sched *s, struct client_task *ct)
 {
        int ret;
 
@@ -327,7 +327,7 @@ static int client_connect(struct client_task *ct)
        ct->task.pre_select = client_pre_select;
        ct->task.post_select = client_post_select;
        sprintf(ct->task.status, "client");
-       register_task(&ct->task);
+       register_task(s, &ct->task);
        return 1;
 err_out:
        close(ct->scc.fd);
@@ -345,6 +345,7 @@ err_out:
  * \param loglevel If not \p NULL, the number of the loglevel is stored here.
  * \param parent Add the new buffer tree node as a child of this node.
  * \param child Add the new buffer tree node as a parent of this node.
+ * \param sched The scheduler instance to register the task to.
  *
  * Check the command line options given by \a argc and argv, set default values
  * for user name and rsa key file, read further option from the config file.
@@ -353,7 +354,8 @@ err_out:
  * \return Standard.
  */
 int client_open(int argc, char *argv[], struct client_task **ct_ptr,
-               int *loglevel, struct btr_node *parent, struct btr_node *child)
+               int *loglevel, struct btr_node *parent, struct btr_node *child,
+               struct sched *sched)
 {
        char *home = para_homedir();
        int ret;
@@ -413,7 +415,7 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr,
        PARA_INFO_LOG("key_file: %s\n", ct->key_file);
        PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
                ct->conf.server_port_arg);
-       ret = client_connect(ct);
+       ret = client_connect(sched, ct);
 out:
        free(home);
        if (ret < 0) {
index b6861b88bbcb36621109f6d9ac7fe80546a42b35..932c9f3a2c7ef51014c9630514513ee427f0280b 100644 (file)
--- a/command.c
+++ b/command.c
@@ -24,6 +24,7 @@
 #include "server.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "net.h"
 #include "daemon.h"
@@ -32,7 +33,6 @@
 #include "user_list.h"
 #include "server_command_list.h"
 #include "afs_command_list.h"
-#include "sched.h"
 #include "signal.h"
 #include "version.h"
 
index 0484778eb593d342eaa0fd961a521e587a5ef468..53fa54e3fbac6fca71ea6005c10a6fa2e707dd3f 100644 (file)
@@ -24,6 +24,7 @@
 #include "net.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "fd.h"
 #include "close_on_fork.h"
index 0dfc94b1cc7213e024f6bc626c48be79cb09df75..bc9952ae95d9c08d3df61a2bbc8e3ecd4329487f 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -120,7 +120,7 @@ int main(int argc, char *argv[])
        sit->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdin"));
        stdin_set_defaults(sit);
-       register_task(&sit->task);
+       register_task(&s, &sit->task);
 
        fns = para_malloc(conf.filter_given * sizeof(*fns));
        for (i = 0, parent = sit->btrn; i < conf.filter_given; i++) {
@@ -143,13 +143,13 @@ int main(int argc, char *argv[])
                fn->task.pre_select = f->pre_select;
                fn->task.post_select = f->post_select;
                f->open(fn);
-               register_task(&fn->task);
+               register_task(&s, &fn->task);
                parent = fn->btrn;
        }
        sot->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdout", .parent = parent));
        stdout_set_defaults(sot);
-       register_task(&sot->task);
+       register_task(&s, &sot->task);
 
        s.default_timeout.tv_sec = 1;
        s.default_timeout.tv_usec = 0;
index 9109c2f8f6c5f1978eddd356ff7f8e979d73dd8a..e5f42416f57e87256d3e8e77eb94fa26c384046a 100644 (file)
@@ -116,7 +116,7 @@ static void gc_post_select(struct sched *s, struct task *t);
  *
  * \param gc The grab client to activate.
  */
-static void gc_activate(struct grab_client *gc)
+static void gc_activate(struct grab_client *gc, struct sched *s)
 {
        struct btr_node *root = audiod_get_btr_root(), *parent;
        char *name = gc->name? gc->name : "grab";
@@ -135,7 +135,7 @@ static void gc_activate(struct grab_client *gc)
        snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
        gc->task.status[sizeof(gc->task.status) - 1] = '\0';
        gc->task.error = 0;
-       register_task(&gc->task);
+       register_task(s, &gc->task);
 }
 
 /**
@@ -149,7 +149,7 @@ static void gc_activate(struct grab_client *gc)
  * This function also garbage collects all grab clients whose tasks have been
  * unscheduled.
  */
-void activate_grab_clients(void)
+void activate_grab_clients(struct sched *s)
 {
        struct grab_client *gc, *tmp;
 
@@ -159,7 +159,7 @@ void activate_grab_clients(void)
                        free(gc);
                        continue;
                }
-               gc_activate(gc);
+               gc_activate(gc, s);
        }
 }
 
@@ -266,6 +266,7 @@ static int gc_check_args(int argc, char **argv, struct grab_client *gc)
  * \param fd The file descriptor of the client.
  * \param argc Argument count.
  * \param argv Argument vector.
+ * \param s The scheduler to register the grab client task to.
  *
  * If the command line options given by \a argc and \a argv are valid.
  * allocate a struct grab_client and initialize it with this valid
@@ -276,7 +277,7 @@ static int gc_check_args(int argc, char **argv, struct grab_client *gc)
  *
  * \return Standard.
  */
-int grab_client_new(int fd, int argc, char **argv)
+int grab_client_new(int fd, int argc, char **argv, struct sched *s)
 {
        int ret;
        struct grab_client *gc = para_calloc(sizeof(struct grab_client));
@@ -286,7 +287,7 @@ int grab_client_new(int fd, int argc, char **argv)
                goto err_out;
        gc->fd = fd;
        para_list_add(&gc->node, &inactive_grab_client_list);
-       gc_activate(gc);
+       gc_activate(gc, s);
        return 1;
 err_out:
        free(gc);
index 88b954837f93f67e5965c4829e0fcb4d0e9856d0..2465d88bc877652fc1ef15cb4ec95a5543b8f342 100644 (file)
@@ -6,5 +6,5 @@
 
 /** \file grab_client.h exported symbols from grab_client.c */
 
-int grab_client_new(int fd, int argc, char **argv);
-void activate_grab_clients(void);
+int grab_client_new(int fd, int argc, char **argv, struct sched *s);
+void activate_grab_clients(struct sched *s);
index 8ae2341a0351d9edc447f544c33fd66e0fb6c74a..50211701b2f3df2c5fd8e919b352b7c967961b3a 100644 (file)
@@ -21,6 +21,7 @@
 #include "http.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "close_on_fork.h"
 #include "net.h"
diff --git a/recv.c b/recv.c
index 52f457fc29b68e61ba017079511145f4e3120885..9b63f517cd77cccd27db0cd4ddcc1dae99c8e082 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -102,12 +102,12 @@ int main(int argc, char *argv[])
        sot.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.parent = rn.btrn, .name = "stdout"));
        stdout_set_defaults(&sot);
-       register_task(&sot.task);
+       register_task(&s, &sot.task);
 
        rn.task.pre_select = r->pre_select;
        rn.task.post_select = r->post_select;
        sprintf(rn.task.status, "%s", r->name);
-       register_task(&rn.task);
+       register_task(&s, &rn.task);
 
        ret = schedule(&s);
 out:
diff --git a/sched.c b/sched.c
index 66a17418027a5e9fa2d92bee412cf682561115b9..041cf417723bd848ea56d2c7eb4935943abeeaef 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -20,9 +20,6 @@
 #include "time.h"
 #include "error.h"
 
-static struct list_head pre_select_list, post_select_list;
-static int initialized;
-
 static struct timeval now_struct;
 struct timeval *now = &now_struct;
 
@@ -36,8 +33,6 @@ struct timeval *now = &now_struct;
  */
 static void unregister_task(struct task *t)
 {
-       if (!initialized)
-               return;
        assert(t->error < 0);
        PARA_INFO_LOG("unregistering %s (%s)\n", t->status,
                para_strerror(-t->error));
@@ -56,7 +51,7 @@ static inline bool timeout_is_zero(struct sched *s)
 static void sched_preselect(struct sched *s)
 {
        struct task *t, *tmp;
-       list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
                if (t->error < 0) {
                        unregister_task(t);
                        continue;
@@ -93,7 +88,7 @@ static void sched_post_select(struct sched *s)
 {
        struct task *t, *tmp;
 
-       list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
                if (t->error >= 0)
                        call_post_select(s, t);
 //             PARA_INFO_LOG("%s: %d\n", t->status, t->ret);
@@ -105,7 +100,7 @@ static void sched_post_select(struct sched *s)
                 * this case t has been unregistered already, so we must not
                 * unregister it again.
                 */
-               if (list_empty(&post_select_list))
+               if (list_empty(&s->post_select_list))
                        return;
                unregister_task(t);
        }
@@ -130,8 +125,6 @@ int schedule(struct sched *s)
 {
        int ret;
 
-       if (!initialized)
-               return -E_NOT_INITIALIZED;
        if (!s->select_function)
                s->select_function = para_select;
 again:
@@ -141,7 +134,7 @@ again:
        s->max_fileno = -1;
        gettimeofday(now, NULL);
        sched_preselect(s);
-       if (list_empty(&pre_select_list) && list_empty(&post_select_list))
+       if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
                return 0;
        if (!timeout_is_zero(s)) {
                ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
@@ -164,44 +157,36 @@ again:
                FD_ZERO(&s->wfds);
        }
        sched_post_select(s);
-       if (list_empty(&pre_select_list) && list_empty(&post_select_list))
+       if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
                return 0;
        goto again;
 }
 
-/*
- * Initialize the paraslash scheduler.
- */
-static void init_sched(void)
-{
-       PARA_INFO_LOG("initializing scheduler\n");
-       INIT_LIST_HEAD(&pre_select_list);
-       INIT_LIST_HEAD(&post_select_list);
-       initialized = 1;
-}
-
 /**
  * Add a task to the scheduler.
  *
- * \param t the task to add
+ * \param t The task to add.
+ * \param s The scheduler instance to add the task to.
  *
  * If the pre_select pointer of \a t is not \p NULL, it is added to
  * the pre_select list of the scheduler. Same goes for post_select.
  *
  * \sa task::pre_select, task::post_select
  */
-void register_task(struct task *t)
+void register_task(struct sched *s, struct task *t)
 {
-       if (!initialized)
-               init_sched();
        PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
+       if (!s->pre_select_list.next)
+               INIT_LIST_HEAD(&s->pre_select_list);
+       if (!s->post_select_list.next)
+               INIT_LIST_HEAD(&s->post_select_list);
        if (t->pre_select) {
                PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
-               list_add_tail(&t->pre_select_node, &pre_select_list);
+               list_add_tail(&t->pre_select_node, &s->pre_select_list);
        }
        if (t->post_select) {
                PARA_DEBUG_LOG("post_select: %p\n", &t->post_select);
-               list_add_tail(&t->post_select_node, &post_select_list);
+               list_add_tail(&t->post_select_node, &s->post_select_list);
        }
 }
 
@@ -212,21 +197,18 @@ void register_task(struct task *t)
  * \a pre_select_list and the \a post_select_list are empty. This function
  * must be called from the post_select (rather than the pre_select) method.
  */
-void sched_shutdown(void)
+void sched_shutdown(struct sched *s)
 {
        struct task *t, *tmp;
 
-       if (!initialized)
-               return;
-       list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
                t->error = -E_SCHED_SHUTDOWN;
                unregister_task(t);
        }
-       list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
                t->error = -E_SCHED_SHUTDOWN;
                unregister_task(t);
        }
-       initialized = 0;
 }
 
 /**
@@ -237,20 +219,18 @@ void sched_shutdown(void)
  * Each entry of the list contains an identifier which is simply a hex number.
  * The result is dynamically allocated and must be freed by the caller.
  */
-char *get_task_list(void)
+char *get_task_list(struct sched *s)
 {
        struct task *t, *tmp;
        char *msg = NULL;
 
-       if (!initialized)
-               return NULL;
-       list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
                char *tmp_msg;
                tmp_msg = make_message("%s%p\tpre\t%s\n", msg? msg : "", t, t->status);
                free(msg);
                msg = tmp_msg;
        }
-       list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
                char *tmp_msg;
 //             if (t->pre_select)
 //                     continue;
diff --git a/sched.h b/sched.h
index ea9578f7b05b3bae17e69e87543675e902d0c590..b3df0b66b180bd1f3f2f48f784c07a187fbac712 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -29,6 +29,10 @@ struct sched {
        int max_fileno;
        /** If non-NULL, use this function instead of para_select. */
        int (*select_function)(int, fd_set *, fd_set *, struct timeval *);
+       /** Currently active pre_select functions. */
+       struct list_head pre_select_list;
+       /** Currently active post_select functions. */
+       struct list_head post_select_list;
 };
 
 /**
@@ -74,10 +78,10 @@ struct task {
  */
 extern struct timeval *now;
 
-void register_task(struct task *t);
+void register_task(struct sched *s, struct task *t);
 int schedule(struct sched *s);
-char *get_task_list(void);
-void sched_shutdown(void);
+char *get_task_list(struct sched *s);
+void sched_shutdown(struct sched *s);
 void sched_min_delay(struct sched *s);
 void sched_request_timeout(struct timeval *to, struct sched *s);
 void sched_request_timeout_ms(long unsigned ms, struct sched *s);
index e786f996ad3b85218d9953a01fee6a86f34b6de4..5bd7d5708ac835553125d1591407d63e79d0add4 100644 (file)
@@ -22,6 +22,7 @@
 #include "send.h"
 #include "close_on_fork.h"
 #include "chunk_queue.h"
+#include "sched.h"
 #include "vss.h"
 
 /** Clients will be kicked if there are more than that many bytes pending. */
index 4650f9947f01ed7fd6f1323610090ae16ef22ac4..ef79a2e88d7577dc882fba229d9141a0c55a1549 100644 (file)
--- a/server.c
+++ b/server.c
@@ -79,6 +79,7 @@
 #include "server.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "config.h"
 #include "close_on_fork.h"
@@ -86,7 +87,6 @@
 #include "daemon.h"
 #include "ipc.h"
 #include "fd.h"
-#include "sched.h"
 #include "signal.h"
 #include "user_list.h"
 #include "color.h"
@@ -123,6 +123,7 @@ int mmd_mutex;
 /** The file containing user information (public key, permissions). */
 static char *user_list_file = NULL;
 
+static struct sched sched;
 
 /** The task responsible for server command handling. */
 struct server_command_task {
@@ -346,7 +347,7 @@ static void init_signal_task(void)
        para_install_sighandler(SIGCHLD);
        para_sigaction(SIGPIPE, SIG_IGN);
        add_close_on_fork_list(st->fd);
-       register_task(&st->task);
+       register_task(&sched, &st->task);
 }
 
 static void command_pre_select(struct sched *s, struct task *t)
@@ -429,7 +430,7 @@ static void init_server_command_task(int argc, char **argv)
                goto err;
        add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
        sprintf(sct->task.status, "server command task");
-       register_task(&sct->task);
+       register_task(&sched, &sct->task);
        return;
 err:
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
@@ -519,7 +520,7 @@ static void server_init(int argc, char **argv)
        init_signal_task();
        para_unblock_signal(SIGCHLD);
        PARA_NOTICE_LOG("initializing virtual streaming system\n");
-       init_vss_task(afs_socket);
+       init_vss_task(afs_socket, &sched);
        init_server_command_task(argc, argv);
        if (conf.daemon_given)
                kill(getppid(), SIGTERM);
@@ -571,16 +572,13 @@ static int server_select(int max_fileno, fd_set *readfds, fd_set *writefds,
 int main(int argc, char *argv[])
 {
        int ret;
-       static struct sched s = {
-               .default_timeout = {
-                       .tv_sec = 1,
-                       .tv_usec = 0
-               },
-               .select_function = server_select
-       };
+
+       sched.default_timeout.tv_sec = 1;
+       sched.select_function = server_select;
+
        server_init(argc, argv);
        mutex_lock(mmd_mutex);
-       ret = schedule(&s);
+       ret = schedule(&sched);
        if (ret < 0) {
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
                exit(EXIT_FAILURE);
index 7a1a89f73e1ab79d91fa2e0978072eaf9e10fc46..880d7957dbd4430819c917cb4b6a9533c96d321c 100644 (file)
 #include "server.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "portable_io.h"
 #include "net.h"
 #include "fd.h"
-#include "sched.h"
 #include "close_on_fork.h"
 
 /**
diff --git a/vss.c b/vss.c
index 4a8aafa8d6e0c2ae239d09342ac10f3b08263828..17d46919b53ea962aa7c52a6c2ed88d251f1dbf7 100644 (file)
--- a/vss.c
+++ b/vss.c
 #include "server.cmdline.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "ipc.h"
 #include "fd.h"
-#include "sched.h"
 
 extern struct misc_meta_data *mmd;
 
@@ -1157,11 +1157,12 @@ static void vss_post_select(struct sched *s, struct task *t)
  * Initialize the virtual streaming system task.
  *
  * \param afs_socket The fd for communication with afs.
+ * \param s The scheduler to register the vss task to.
  *
  * This also initializes all supported senders and starts streaming
  * if the --autoplay command line flag was given.
  */
-void init_vss_task(int afs_socket)
+void init_vss_task(int afs_socket, struct sched *s)
 {
        static struct vss_task vss_task_struct, *vsst = &vss_task_struct;
        int i;
@@ -1194,5 +1195,5 @@ void init_vss_task(int afs_socket)
                        &vsst->data_send_barrier);
        }
        sprintf(vsst->task.status, "vss task");
-       register_task(&vsst->task);
+       register_task(s, &vsst->task);
 }
diff --git a/vss.h b/vss.h
index bd798b0cfdaf454faee5816c3b16ffbed99e112b..ae53f6eccf8327c6035c6f33dceb01b0268e3616 100644 (file)
--- a/vss.h
+++ b/vss.h
@@ -6,7 +6,7 @@
 
 /** \file vss.h Exported functions from vss.c (para_server). */
 
-void init_vss_task(int afs_socket);
+void init_vss_task(int afs_socket, struct sched *s);
 unsigned int vss_playing(void);
 unsigned int vss_next(void);
 unsigned int vss_repos(void);
diff --git a/write.c b/write.c
index 3b5f2d193f31ddc1d8c130703637810f807f255f..afaad951922b0e02a973913327e2d92ee39d2631 100644 (file)
--- a/write.c
+++ b/write.c
@@ -186,7 +186,7 @@ __noreturn static void print_help_and_die(void)
  * \return Standard.
  */
 static void setup_writer_node(const char *arg, struct btr_node *parent,
-               struct writer_node *wn)
+               struct writer_node *wn, struct sched *s)
 {
        if (arg)
                wn->conf = check_writer_arg_or_die(arg, &wn->writer_num);
@@ -194,7 +194,7 @@ static void setup_writer_node(const char *arg, struct btr_node *parent,
                wn->writer_num = DEFAULT_WRITER;
                wn->conf = writers[DEFAULT_WRITER].parse_config_or_die("");
        }
-       register_writer_node(wn, parent);
+       register_writer_node(wn, parent, s);
 }
 
 static int setup_and_schedule(void)
@@ -208,7 +208,7 @@ static int setup_and_schedule(void)
        sit.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdin"));
        stdin_set_defaults(&sit);
-       register_task(&sit.task);
+       register_task(&s, &sit.task);
 
        cwt->state = CWS_NEED_HEADER;
        cwt->min_iqs = WAV_HEADER_LEN;
@@ -219,17 +219,17 @@ static int setup_and_schedule(void)
        cwt->task.pre_select = check_wav_pre_select;
        cwt->task.post_select = check_wav_post_select;
        cwt->task.error = 0;
-       register_task(&cwt->task);
+       register_task(&s, &cwt->task);
 
        if (!conf.writer_given) {
                wns = para_calloc(sizeof(*wns));
-               setup_writer_node(NULL, cwt->btrn, wns);
+               setup_writer_node(NULL, cwt->btrn, wns, &s);
                i = 1;
        } else {
                wns = para_calloc(conf.writer_given * sizeof(*wns));
                for (i = 0; i < conf.writer_given; i++)
                        setup_writer_node(conf.writer_arg[i], cwt->btrn,
-                               wns + i);
+                               wns + i, &s);
        }
 
        s.default_timeout.tv_sec = 10;
index b85699367acd45d88eb4044da6450d2717f48437..71b6664d012d80cb397e524c3370347bb87a3956 100644 (file)
@@ -77,11 +77,13 @@ void *check_writer_arg_or_die(const char *wa, int *writer_num)
  *
  * \param wn The writer node to open.
  * \param parent The parent btr node (the source for the writer node).
+ * \param s The scheduler instance to register the task to.
  *
  * The configuration of the writer node stored in \p wn->conf must be
  * initialized before this function may be called.
  */
-void register_writer_node(struct writer_node *wn, struct btr_node *parent)
+void register_writer_node(struct writer_node *wn, struct btr_node *parent,
+               struct sched *s)
 {
        struct writer *w = writers + wn->writer_num;
        char *name = make_message("%s writer", writer_names[wn->writer_num]);
@@ -93,7 +95,7 @@ void register_writer_node(struct writer_node *wn, struct btr_node *parent)
        free(name);
        wn->task.post_select = w->post_select;
        wn->task.pre_select = w->pre_select;
-       register_task(&wn->task);
+       register_task(s, &wn->task);
 }
 
 /**
index 00ded8f37bb29f4219340286edee7f66a82fa0bf..68eb4063147fc4f41e4d66334aca10bab6d7d668 100644 (file)
@@ -9,7 +9,8 @@
 void writer_init(void);
 void *check_writer_arg_or_die(const char *wa, int *writer_num);
 void print_writer_helps(int detailed);
-void register_writer_node(struct writer_node *wn, struct btr_node *parent);
+void register_writer_node(struct writer_node *wn, struct btr_node *parent,
+               struct sched *s);
 void get_btr_sample_rate(struct btr_node *btrn, int32_t *result);
 void get_btr_channels(struct btr_node *btrn, int32_t *result);
 void get_btr_sample_format(struct btr_node *btrn, int32_t *result);