From 5edb8fd098c2f392702a7b07bda664f1acf4b350 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 8 Jul 2012 18:57:24 +0000 Subject: [PATCH] sched: Replace sched_shutdown() by task_notify_all(). 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 | 10 ++++++++-- sched.c | 50 +++++++++++++++++++------------------------------- sched.h | 2 +- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/afs.c b/afs.c index f1e28f14..1f3fafac 100644 --- 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 e67579b3..ae82b233 100644 --- 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 9d4d52e2..74c3fc65 100644 --- 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); -- 2.39.5