+#include <sys/time.h>
+#include "para.h"
+#include "ipc.h"
+#include "fd.h"
+#include "list.h"
+#include "sched.h"
+#include "string.h"
+#include "error.h"
+
+struct list_head pre_select_list;
+struct list_head post_select_list;
+
+static void sched_preselect(struct sched *s)
+{
+ struct task *t, *tmp;
+again:
+ list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+ t->pre_select(s, t);
+ if (t->ret > 0 || !t->error_handler)
+ continue;
+ if (t->ret < 0) {
+ t->error_handler(t);
+ goto again;
+ }
+ if (!(t->flags & PRE_EOF_IS_ERROR))
+ continue;
+ t->ret = -E_PRE_EOF;
+ t->error_handler(t);
+ goto again;
+ }
+}
+
+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->ret > 0 || !t->error_handler)
+ continue;
+ if (t->ret < 0) {
+ t->error_handler(t);
+ continue;
+ }
+ if (!(t->flags & POST_EOF_IS_ERROR))
+ continue;
+ t->ret = -E_POST_EOF;
+ t->error_handler(t);
+ }
+}
+
+int sched(struct sched *s)
+{
+
+ gettimeofday(&s->now, NULL);
+again:
+ FD_ZERO(&s->rfds);
+ FD_ZERO(&s->wfds);
+ s->timeout = s->default_timeout;
+ s->max_fileno = -1;
+ sched_preselect(s);
+ s->select_ret = para_select(s->max_fileno + 1, &s->rfds,
+ &s->wfds, &s->timeout);
+ if (s->select_ret < 0)
+ return s->select_ret;
+ gettimeofday(&s->now, NULL);
+ sched_post_select(s);
+ if (list_empty(&pre_select_list) && list_empty(&post_select_list))
+ return 0;
+ goto again;
+}
+
+void *register_task(struct task *t)
+{
+ PARA_INFO_LOG("registering task %p\n", t);
+ if (t->pre_select) {
+ PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
+ if (t->flags & PRE_ADD_TAIL)
+ list_add_tail(&t->pre_select_node, &pre_select_list);
+ else
+ list_add(&t->pre_select_node, &pre_select_list);
+ }
+ if (t->post_select) {
+ PARA_DEBUG_LOG("post_select: %p\n", &t->pre_select);
+ if (t->flags & POST_ADD_TAIL)
+ list_add_tail(&t->post_select_node, &post_select_list);
+ else
+ list_add(&t->post_select_node, &post_select_list);
+ }
+ return t;
+}
+
+void unregister_task(struct task *t)
+{
+ PARA_INFO_LOG("unregistering task %p\n", t);
+ if (t->pre_select)
+ list_del(&t->pre_select_node);
+ if (t->post_select)
+ list_del(&t->post_select_node);
+};
+
+void init_sched(void)
+{
+ INIT_LIST_HEAD(&pre_select_list);
+ INIT_LIST_HEAD(&post_select_list);
+};
+
+void sched_shutdown(void)
+{
+ struct task *t, *tmp;
+
+ 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);
+};
+
+
+//char *get_tast_list();