MAJOR: task: task scheduler rework.
In order to authorize call of task_wakeup on running task:
- from within the task handler itself.
- in futur, from another thread.
The lookups on runqueue and waitqueue are re-worked
to prepare multithread stuff.
If task_wakeup is called on a running task, the woken
message flags are savec in the 'pending_state' attribute of
the state. The real wakeup is postponed at the end of the handler
process and the woken messages are copied from pending_state
to the state attribute of the task.
It's important to note that this change will cause a very minor
(though measurable) performance loss but it is necessary to make
forward progress on a multi-threaded scheduler. Most users won't
ever notice.
diff --git a/include/proto/task.h b/include/proto/task.h
index 70fd0b3..e510cd9 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -85,8 +85,6 @@
extern unsigned int nb_tasks_cur;
extern unsigned int niced_tasks; /* number of niced tasks in the run queue */
extern struct pool_head *pool2_task;
-extern struct eb32_node *last_timer; /* optimization: last queued timer */
-extern struct eb32_node *rq_next; /* optimization: next task except if delete/insert */
/* return 0 if task is in run queue, otherwise non-zero */
static inline int task_in_rq(struct task *t)
@@ -104,6 +102,13 @@
struct task *__task_wakeup(struct task *t);
static inline struct task *task_wakeup(struct task *t, unsigned int f)
{
+ /* If task is running, we postpone the call
+ * and backup the state.
+ */
+ if (unlikely(t->state & TASK_RUNNING)) {
+ t->pending_state |= f;
+ return t;
+ }
if (likely(!task_in_rq(t)))
__task_wakeup(t);
t->state |= f;
@@ -119,8 +124,6 @@
static inline struct task *__task_unlink_wq(struct task *t)
{
eb32_delete(&t->wq);
- if (last_timer == &t->wq)
- last_timer = NULL;
return t;
}
@@ -153,8 +156,6 @@
static inline struct task *task_unlink_rq(struct task *t)
{
if (likely(task_in_rq(t))) {
- if (&t->rq == rq_next)
- rq_next = eb32_next(rq_next);
__task_unlink_rq(t);
}
return t;
@@ -180,7 +181,7 @@
{
t->wq.node.leaf_p = NULL;
t->rq.node.leaf_p = NULL;
- t->state = TASK_SLEEPING;
+ t->pending_state = t->state = TASK_SLEEPING;
t->nice = 0;
t->calls = 0;
return t;