+/*
+ * Copyright (C) 2006 Andre Noll <maan@systemlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ */
+
+/** \file sched.c paraslash's scheduling functions */
+
#include <sys/time.h>
#include "para.h"
#include "ipc.h"
#include "string.h"
#include "error.h"
-struct list_head pre_select_list;
-struct list_head post_select_list;
+/**
+ * The scheduler 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.
+ */
+struct list_head pre_select_list, post_select_list;
static struct timeval now_struct;
+
struct timeval *now = &now_struct;
static void sched_preselect(struct sched *s)
}
}
+/**
+ * the core function for all paraslash programs
+ *
+ * Short and sweet. It updates the global \a now pointer, calls all registered
+ * pre_select hooks which may set the timeout and add any file descriptors to
+ * 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.
+ *
+ * \sa task, now.
+ */
int sched(struct sched *s)
{
goto again;
}
-void *register_task(struct task *t)
+/**
+ * add a task to the scheduler
+ *
+ * \param t the task to add
+ *
+ * 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)
{
PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
if (t->pre_select) {
PARA_DEBUG_LOG("post_select: %p\n", &t->pre_select);
list_add(&t->post_select_node, &post_select_list);
}
- return t;
}
+/**
+ * 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.
+ */
void unregister_task(struct task *t)
{
PARA_INFO_LOG("unregistering %s (%p)\n", t->status, t);
list_del(&t->post_select_node);
};
+/**
+ * initialize the paraslash scheduler
+ */
void init_sched(void)
{
INIT_LIST_HEAD(&pre_select_list);
INIT_LIST_HEAD(&post_select_list);
};
+/**
+ * unregister all tasks
+ *
+ * This will cause \a sched() to return immediately because both the
+ * \a pre_select_list and the \a post_select_list are empty.
+ */
void sched_shutdown(void)
{
struct task *t, *tmp;
unregister_task(t);
};
+/**
+ * get the list of all registered tasks.
+ *
+ * \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.
+ * The result ist dynamically allocated and must be freed by the caller.
+ */
char *get_task_list(void)
{
struct task *t, *tmp;
return msg;
}
+/**
+ * simulate an error for the given task
+ *
+ * \param id the task identifier
+ *
+ * Find the task identified by \a id, set the tasks' return value to
+ * \p -E_TASK_KILLED and call the event handler of the task.
+ *
+ * \return Positive on sucess, negative if \a id does not correspond to a
+ * registered task.
+ */
int kill_task(char *id)
{
struct task *t, *tmp;
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
-/** \file sched.c Paraslash's task and scheduling functions */
+/** \file sched.h sched and task structures and exported symbols from sched.c */
/**
* before registering a task to the scheduler, the task structure must be
* filled in properly by the caller.
*
- * The pre_select or the post_select pointer, but not both may be NULL. Once
- * a task is registered, its pre_select and post_select function gets called
- * from the scheduler's mainloop. The purpose of the pre_select loop is to add
- * file descriptors to the fd sets of the scheduler and to decrease the select
- * timeout if neccessary. The post_select function may then evaluate these fd
- * sets and act upon the results.
-
* If one of these functions return a negative value via \a t->ret the
* (optional) event_handler gets called (it may also be called in case another
* event happend). In many cases the only possible event is an error or an eof
struct task {
/** pointer to the struct this task is embedded in */
void *private_data;
- /** pre_select hook */
+ /**
+ * the 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 neccessary.
+ */
void (*pre_select)(struct sched *s, struct task *t);
- /** post_select hook */
+ /**
+ * the postselect hook of \a t
+ *
+ * evaluate and act upon the results of the previous select call.
+ */
void (*post_select)(struct sched *s, struct task *t);
- /** gets called */
+ /** gets called if pre_select or post_select returned an error */
void (*event_handler)(struct task *t);
/** pre_select() and post_select store their return value here */
int ret;
*/
extern struct timeval *now;
-void *register_task(struct task *t);
+void register_task(struct task *t);
void unregister_task(struct task *t);
int sched(struct sched *s);
void init_sched(void);
* \param t the task structure of the stdin task
*
* This function is always successful. If there is space left in the
- * buffer of the stdin task, it adds \a STDIN_FILENO to the read fd set
+ * buffer of the stdin task, it adds \p STDIN_FILENO to the read fd set
* of \a s.
*/
void stdin_pre_select(struct sched *s, struct task *t)
* \param s the scheduler this task was registered to
* \param t the task structure of the stdin task
*
- * This function checks if \a STDIN_FILENO was included by in the read fd set
- * of \a s during the previous pre_select call. If yes, and STDIN_FILENO
+ * This function checks if \p STDIN_FILENO was included by in the read fd set
+ * of \a s during the previous pre_select call. If yes, and \p STDIN_FILENO
* appeears to be readable, data is read from stdin into the buffer of the
* stdin task.
*/
#include "error.h"
#include "stdout.h"
-
/**
* the pre_select function of the stdout task
*
* \param t the task structure of the stdout task
*
* This function is always successful. If there is data available in the input
- * buffer, it adds \a STDOUT_FILENO to the write fd set of \a s.
+ * buffer, it adds \p STDOUT_FILENO to the write fd set of \a s.
*/
void stdout_pre_select(struct sched *s, struct task *t)
{
* \param s the scheduler this task was registered to
* \param t the task structure of the stdout task
*
- * This function checks if \a STDOUT_FILENO was included by in the write fd set
- * of \a s during the previous pre_select call. If yes, and STDOUT_FILENO
+ * This function checks if \p STDOUT_FILENO was included by in the write fd set
+ * of \a s during the previous pre_select call. If yes, and \p STDOUT_FILENO
* appeears to be writable, the data loaded in the input buffer is written to
* stdout.
*/