sched: Replace sched_shutdown() by task_notify_all().
authorAndre Noll <maan@systemlinux.org>
Sun, 8 Jul 2012 18:57:24 +0000 (18:57 +0000)
committerAndre Noll <maan@systemlinux.org>
Sun, 18 Nov 2012 19:28:27 +0000 (20:28 +0100)
sched_shutdown() was mis-designed from the beginning as the registered
tasks have no chance to clean up. Using task notifiers allows to
replace the single caller of sched_shutdown().

afs.c
sched.c
sched.h

diff --git a/afs.c b/afs.c
index f1e28f1..1f3fafa 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -744,7 +744,7 @@ static void afs_signal_post_select(struct sched *s, struct task *t)
        }
        PARA_EMERG_LOG("terminating on signal %d\n", signum);
 shutdown:
-       sched_shutdown(s);
+       task_notify_all(s, E_AFS_SIGNAL);
        t->error = -E_AFS_SIGNAL;
 }
 
@@ -921,10 +921,16 @@ static void command_post_select(struct sched *s, struct task *t)
        struct afs_client *client, *tmp;
        int fd, ret;
 
+       ret = task_get_notification(t);
+       if (ret < 0) {
+               t->error = ret;
+               return;
+       }
        ret = execute_server_command(&s->rfds);
        if (ret < 0) {
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-               sched_shutdown(s);
+               task_notify_all(s, -ret);
+               t->error = ret;
                return;
        }
        /* Check the list of connected clients. */
diff --git a/sched.c b/sched.c
index e67579b..ae82b23 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -98,14 +98,6 @@ static void sched_post_select(struct sched *s)
                t->notification = 0;
                if (t->error >= 0)
                        continue;
-               /*
-                * We have to check whether the list is empty because the call
-                * to ->post_select() might have called sched_shutdown(). In
-                * this case t has been unregistered already, so we must not
-                * unregister it again.
-                */
-               if (list_empty(&s->post_select_list))
-                       return;
                unregister_task(t);
        }
 }
@@ -195,29 +187,6 @@ void register_task(struct sched *s, struct task *t)
        }
 }
 
-/**
- * Unregister all tasks.
- *
- * \param s The scheduler instance to shut down.
- *
- * This will cause \a schedule() to return immediately because both the
- * \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(struct sched *s)
-{
-       struct task *t, *tmp;
-
-       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, &s->post_select_list, post_select_node) {
-               t->error = -E_SCHED_SHUTDOWN;
-               unregister_task(t);
-       }
-}
-
 /**
  * Get the list of all registered tasks.
  *
@@ -295,6 +264,25 @@ int task_get_notification(struct task *t)
        return t->notification;
 }
 
+/**
+ * Set the notification value of all tasks of a scheduler instance.
+ *
+ * \param s The scheduler instance whose tasks should be notified.
+ * \param err A positive error code.
+ *
+ * This simply iterates over all existing tasks of \a s and sets each
+ * task's notification value to \p -err.
+ */
+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)
+               task_notify(t, err);
+}
+
 /**
  * Set the select timeout to the minimal possible value.
  *
diff --git a/sched.h b/sched.h
index 9d4d52e..74c3fc6 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -84,7 +84,7 @@ void register_task(struct sched *s, struct task *t);
 int schedule(struct sched *s);
 char *get_task_list(struct sched *s);
 void task_notify(struct task *t, int err);
-void sched_shutdown(struct sched *s);
+void task_notify_all(struct sched *s, int err);
 int task_get_notification(struct task *t);
 void sched_min_delay(struct sched *s);
 void sched_request_timeout(struct timeval *to, struct sched *s);