X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=sched.c;h=b9d642864624cd796e3853331cc9a652378c41c5;hp=90df5933689c377ad2c570e36bb340eda74e9dae;hb=e6940831fbcf21dd0e6243ca89ea0c7f8b195d9e;hpb=bcd7e2c158de891fc1aea06c5783760ab94749e8 diff --git a/sched.c b/sched.c index 90df5933..b9d64286 100644 --- a/sched.c +++ b/sched.c @@ -4,7 +4,7 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file sched.c paraslash's scheduling functions */ +/** \file sched.c Paraslash's scheduling functions. */ #include /* readdir() */ #include @@ -27,7 +27,7 @@ struct timeval *now = &now_struct; /** * Remove a task from the scheduler. * - * \param t the task to remove + * \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. @@ -41,8 +41,7 @@ void unregister_task(struct task *t) list_del(&t->pre_select_node); if (t->post_select) list_del(&t->post_select_node); - if (t->error >= 0) - t->error = -E_TASK_KILLED; + t->error = -E_TASK_UNREGISTERED; }; @@ -50,10 +49,19 @@ static void sched_preselect(struct sched *s) { struct task *t, *tmp; list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) { - t->pre_select(s, t); + if (t->error >= 0) + t->pre_select(s, t); // PARA_INFO_LOG("%s \n", t->status); if (t->error >= 0) continue; + /* + * We have to check whether the list is empty because the call + * to ->pre_select() might have called sched_shutdown(). In + * this case t has been unregistered already, so we must not + * unregister it again. + */ + if (list_empty(&pre_select_list)) + return; unregister_task(t); } } @@ -63,18 +71,22 @@ 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) { - t->post_select(s, t); + if (t->error >= 0) + t->post_select(s, t); // PARA_INFO_LOG("%s: %d\n", t->status, t->ret); if (t->error >= 0) continue; + /* nec., see sched_preselect() */ + if (list_empty(&post_select_list)) + return; unregister_task(t); } } /** - * the core function for all paraslash programs + * The core function for all paraslash programs. * - * \param s pointer to the scheduler struct + * \param s Pointer to the scheduler struct. * * This function updates the global \a now pointer, calls all registered * pre_select hooks which may set the timeout and add any file descriptors to @@ -99,6 +111,8 @@ again: s->timeout = s->default_timeout; s->max_fileno = -1; sched_preselect(s); + if (list_empty(&pre_select_list) && list_empty(&post_select_list)) + return 0; ret = para_select(s->max_fileno + 1, &s->rfds, &s->wfds, &s->timeout); if (ret < 0) return ret; @@ -110,7 +124,7 @@ again: } /** - * initialize the paraslash scheduler + * Initialize the paraslash scheduler. */ static void init_sched(void) { @@ -121,7 +135,7 @@ static void init_sched(void) }; /** - * add a task to the scheduler + * Add a task to the scheduler. * * \param t the task to add * @@ -146,7 +160,7 @@ void register_task(struct task *t) } /** - * unregister all tasks + * Unregister all tasks. * * This will cause \a schedule() to return immediately because both the * \a pre_select_list and the \a post_select_list are empty. @@ -159,16 +173,15 @@ void sched_shutdown(void) return; list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) unregister_task(t); - /* remove tasks which do not have a pre_select hook */ list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) unregister_task(t); initialized = 0; }; /** - * get the list of all registered tasks. + * Get the list of all registered tasks. * - * \return the task list + * \return The task list. * * Each entry of the list contains an identifier which is simply a hex number * that may be used in \a kill_task() to terminate the task. @@ -200,9 +213,9 @@ char *get_task_list(void) } /** - * simulate an error for the given task + * Simulate an error for the given task. * - * \param id the task identifier + * \param id The task identifier. * * Find the task identified by \a id, set the tasks' error value to * \p -E_TASK_KILLED and unregister the task. @@ -222,7 +235,6 @@ int kill_task(char *id) if (strcmp(id, buf)) continue; t->error = -E_TASK_KILLED; - unregister_task(t); return 1; } list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) { @@ -230,7 +242,6 @@ int kill_task(char *id) if (strcmp(id, buf)) continue; t->error = -E_TASK_KILLED; - unregister_task(t); return 1; } return -E_NO_SUCH_TASK;