]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Simplify sched: Use only a single task list.
authorAndre Noll <maan@systemlinux.org>
Mon, 30 Dec 2013 17:37:41 +0000 (17:37 +0000)
committerAndre Noll <maan@systemlinux.org>
Sun, 25 May 2014 13:36:37 +0000 (15:36 +0200)
Currently the scheduler maintains two linked task lists, the pre_select
and the post_select list. This is completely unnecessary and bloats
the code for no good reason. This patch makes it use a single list
only and updates the documentation accordingly.

sched.c
sched.h

diff --git a/sched.c b/sched.c
index 8b68667bf453c481df6950ec727be3b134037f99..86069029f2820a4844fd296a423617a95ae0b4c5 100644 (file)
--- a/sched.c
+++ b/sched.c
 static struct timeval now_struct;
 struct timeval *now = &now_struct;
 
-/*
- * Remove a task from the scheduler.
- *
- * \param t The task to remove.
- *
- * If the pre_select pointer of \a t is not \p NULL, it is removed from
- * the pre_select list of the scheduler. Same goes for \a post_select.
- */
-static void unregister_task(struct task *t)
-{
-       assert(t->error < 0);
-       PARA_INFO_LOG("unregistering %s (%s)\n", t->status,
-               para_strerror(-t->error));
-       if (t->pre_select)
-               list_del(&t->pre_select_node);
-       if (t->post_select)
-               list_del(&t->post_select_node);
-}
-
 static inline bool timeout_is_zero(struct sched *s)
 {
        struct timeval *tv = &s->select_timeout;
@@ -50,7 +31,9 @@ static void sched_preselect(struct sched *s)
 {
        struct task *t, *tmp;
 
-       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
+               if (t->error < 0)
+                       continue;
                if (t->notification != 0)
                        sched_min_delay(s);
                if (t->pre_select)
@@ -82,19 +65,16 @@ static void sched_post_select(struct sched *s)
 {
        struct task *t, *tmp;
 
-       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);
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
+               call_post_select(s, t);
                t->notification = 0;
-               if (t->error >= 0)
-                       continue;
-               unregister_task(t);
+               if (t->error < 0)
+                       list_del(&t->node);
        }
 }
 
 /**
- * The core function for all paraslash programs.
+ * The core function of all paraslash programs.
  *
  * \param s Pointer to the scheduler struct.
  *
@@ -103,10 +83,10 @@ static void sched_post_select(struct sched *s)
  * the fd sets of \a s.  Next, it calls para_select() and makes the result available
  * to the registered tasks by calling their post_select hook.
  *
- * \return Zero if no more tasks are left in either of the two lists, negative
- * if para_select returned an error.
+ * \return Zero if no more tasks are left in the task list, negative if the
+ * select function returned an error.
  *
- * \sa task, now.
+ * \sa \ref task, \ref now.
  */
 int schedule(struct sched *s)
 {
@@ -137,7 +117,7 @@ again:
        }
        clock_get_realtime(now);
        sched_post_select(s);
-       if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
+       if (list_empty(&s->task_list))
                return 0;
        goto again;
 }
@@ -148,27 +128,16 @@ again:
  * \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 sched *s, struct task *t)
 {
        PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
+       assert(t->post_select);
        t->notification = 0;
-       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, &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, &s->post_select_list);
-       }
+       if (!s->task_list.next)
+               INIT_LIST_HEAD(&s->task_list);
+       list_add_tail(&t->node, &s->task_list);
 }
 
 /**
@@ -186,21 +155,12 @@ char *get_task_list(struct sched *s)
        struct task *t, *tmp;
        char *msg = NULL;
 
-       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, &s->post_select_list, post_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
                char *tmp_msg;
-//             if (t->pre_select)
-//                     continue;
-               tmp_msg = make_message("%s%p\tpost\t%s\n", msg? msg : "", t, t->status);
+               tmp_msg = make_message("%s%p\t%s\n", msg? msg : "", t, t->status);
                free(msg);
                msg = tmp_msg;
        }
-       //PARA_DEBUG_LOG("task list:\n%s", msg);
        return msg;
 }
 
@@ -261,9 +221,7 @@ void task_notify_all(struct sched *s, int err)
 {
        struct task *t;
 
-       list_for_each_entry(t, &s->pre_select_list, pre_select_node)
-               task_notify(t, err);
-       list_for_each_entry(t, &s->post_select_list, post_select_node)
+       list_for_each_entry(t, &s->task_list, node)
                task_notify(t, err);
 }
 
diff --git a/sched.h b/sched.h
index f15e4efb666738d5f12da542e3ae10c3d774132e..c706b5093fba47f3173cc183daa07f0b77120a48 100644 (file)
--- a/sched.h
+++ b/sched.h
 /**
  * Paraslash's scheduler.
  *
- * Designed with KISS in mind. It manages two lists of tasks.  The pre_select
- * list contains pointers to functions that are called before calling select()
- * from the main loop. Similarly, \a post_select_list is a list of function
- * pointers each of which is called after the select call. Tasks add hooks to
- * these lists by registering themselves to the scheduler.
+ * Designed with KISS in mind. It maintains a list of task structures which is
+ * extended when a new task is registered. Each task may define a pre_select
+ * function which is called from the scheduler main loop before it calls
+ * select(). Similarly, each task must define a post_select function which is
+ * called after the select call.
  */
 struct sched {
        /** Initial value before any pre_select call. */
@@ -29,10 +29,8 @@ 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;
+       /** Tasks which have been registered to the scheduler. */
+       struct list_head task_list;
 };
 
 /**
@@ -45,26 +43,24 @@ struct sched {
  */
 struct task {
        /**
-        * The pre select hook of \a t.
+        * The optional pre select hook of \a t.
         *
         * Its purpose is to add file descriptors to the fd sets of the
         * scheduler and to decrease the select timeout if necessary.
         */
        void (*pre_select)(struct sched *s, struct task *t);
        /**
-        * The post select hook of \a t.
+        * The mandatory post select hook of \a t.
         *
         * Its purpose is to evaluate and act upon the results of the previous
         * select call. If this function returns a negative value, the
         * scheduler unregisters the task.
         */
        int (*post_select)(struct sched *s, struct task *t);
-       /** Whether this task is in error state. */
+       /** Whether this task is active (>=0) or in error state (<0). */
        int error;
-       /** Position of the task in the pre_select list of the scheduler. */
-       struct list_head pre_select_node;
-       /** Position of the task in the post_select list of the scheduler. */
-       struct list_head post_select_node;
+       /** Position of the task in the task list of the scheduler. */
+       struct list_head node;
        /** Descriptive text and current status of the task. */
        char status[255];
        /** If less than zero, the task was notified by another task. */