[MEDIUM] indicate a reason for a task wakeup
It's very frequent to require some information about the
reason why a task is running. Some flags have been added
so that a task now knows if it got woken up due to I/O
completion, timeout, etc...
diff --git a/include/proto/task.h b/include/proto/task.h
index fbb9ee8..c923a98 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -40,13 +40,14 @@
/* perform minimal initializations, report 0 in case of error, 1 if OK. */
int init_task();
-/* puts the task <t> in run queue <q>, and returns <t> */
+/* puts the task <t> in run queue with reason flags <f>, and returns <t> */
struct task *__task_wakeup(struct task *t);
-static inline struct task *task_wakeup(struct task *t)
+static inline struct task *task_wakeup(struct task *t, unsigned int f)
{
- if (t->state == TASK_RUNNING)
- return t;
- return __task_wakeup(t);
+ if (likely(!(t->state & TASK_IN_RUNQUEUE)))
+ __task_wakeup(t);
+ t->state |= f;
+ return t;
}
/* removes the task <t> from the run queue if it was in it.
@@ -54,8 +55,8 @@
*/
static inline struct task *task_sleep(struct task *t)
{
- if (t->state == TASK_RUNNING) {
- t->state = TASK_IDLE;
+ if (t->state & TASK_IN_RUNQUEUE) {
+ t->state = TASK_SLEEPING;
eb32_delete(&t->eb);
run_queue--;
if (likely(t->nice))
@@ -87,7 +88,7 @@
static inline struct task *task_delete(struct task *t)
{
task_dequeue(t);
- if (t->state == TASK_RUNNING) {
+ if (t->state & TASK_IN_RUNQUEUE) {
run_queue--;
if (likely(t->nice))
niced_tasks--;
@@ -102,7 +103,7 @@
static inline struct task *task_init(struct task *t)
{
t->eb.node.leaf_p = NULL;
- t->state = TASK_IDLE;
+ t->state = TASK_SLEEPING;
t->nice = 0;
return t;
}
diff --git a/include/types/task.h b/include/types/task.h
index ae9166e..13207bb 100644
--- a/include/types/task.h
+++ b/include/types/task.h
@@ -29,13 +29,25 @@
#include <common/mini-clist.h>
/* values for task->state */
-#define TASK_IDLE 0
-#define TASK_RUNNING 1
+#define TASK_SLEEPING 0x00 /* task sleeping */
+#define TASK_IN_RUNQUEUE 0x01 /* the task is in the run queue */
+#define TASK_WOKEN_INIT 0x02 /* woken up for initialisation purposes */
+#define TASK_WOKEN_TIMER 0x04 /* woken up because of expired timer */
+#define TASK_WOKEN_IO 0x08 /* woken up because of completed I/O */
+#define TASK_WOKEN_SIGNAL 0x10 /* woken up by a system signal */
+#define TASK_WOKEN_MSG 0x20 /* woken up by another task's message */
+#define TASK_WOKEN_RES 0x40 /* woken up because of available resource */
+#define TASK_WOKEN_OTHER 0x80 /* woken up for an unspecified reason */
+
+/* use this to check a task state or to clean it up before queueing */
+#define TASK_WOKEN_ANY (TASK_WOKEN_OTHER|TASK_WOKEN_INIT|TASK_WOKEN_TIMER| \
+ TASK_WOKEN_IO|TASK_WOKEN_SIGNAL|TASK_WOKEN_MSG| \
+ TASK_WOKEN_RES)
/* The base for all tasks */
struct task {
struct eb32_node eb; /* ebtree node used to hold the task in the wait queue */
- int state; /* task state : IDLE or RUNNING */
+ int state; /* task state : bit field of TASK_* */
unsigned int expire; /* next expiration time for this task */
void (*process)(struct task *t, int *next); /* the function which processes the task */
void *context; /* the task's context */
diff --git a/src/checks.c b/src/checks.c
index 5e3c19d..7140be4 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -73,7 +73,7 @@
sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
pendconn_free(pc);
- task_wakeup(sess->task);
+ task_wakeup(sess->task, TASK_WOKEN_RES);
xferred++;
}
}
@@ -102,7 +102,7 @@
p->sess->srv = s;
sess = p->sess;
pendconn_free(p);
- task_wakeup(sess->task);
+ task_wakeup(sess->task, TASK_WOKEN_RES);
}
return xferred;
}
@@ -404,7 +404,7 @@
}
}
out_wakeup:
- task_wakeup(t);
+ task_wakeup(t, TASK_WOKEN_IO);
out_nowake:
EV_FD_CLR(fd, DIR_WR); /* nothing more to write */
fdtab[fd].ev &= ~FD_POLL_OUT;
@@ -512,7 +512,7 @@
fdtab[fd].state = FD_STERROR;
EV_FD_CLR(fd, DIR_RD);
- task_wakeup(t);
+ task_wakeup(t, TASK_WOKEN_IO);
fdtab[fd].ev &= ~FD_POLL_IN;
return 1;
}
diff --git a/src/client.c b/src/client.c
index 606cf79..5ff1abe 100644
--- a/src/client.c
+++ b/src/client.c
@@ -409,7 +409,7 @@
* priorities to tasks.
*/
if (p->mode != PR_MODE_HEALTH)
- task_wakeup(t);
+ task_wakeup(t, TASK_WOKEN_INIT);
p->feconn++; /* beconn will be increased later */
if (p->feconn > p->feconn_max)
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 2185f9f..4eab55e 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -520,7 +520,7 @@
t->expire = s->req->rex;
}
- task_wakeup(t);
+ task_wakeup(t, TASK_WOKEN_INIT);
l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
if (l->nbconn >= l->maxconn) {
diff --git a/src/queue.c b/src/queue.c
index 3b7fd4b..dd5bb04 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -77,7 +77,7 @@
struct session *sess = pendconn_get_next_sess(s, p);
if (sess == NULL)
break;
- task_wakeup(sess->task);
+ task_wakeup(sess->task, TASK_WOKEN_RES);
}
}
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 459da71..52860ea 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -239,7 +239,7 @@
if (!(b->flags & BF_READ_ACTIVITY))
goto out_skip_wakeup;
out_wakeup:
- task_wakeup(fdtab[fd].owner);
+ task_wakeup(fdtab[fd].owner, TASK_WOKEN_IO);
out_skip_wakeup:
fdtab[fd].ev &= ~FD_POLL_IN;
@@ -411,7 +411,7 @@
if (!(b->flags & BF_WRITE_ACTIVITY))
goto out_skip_wakeup;
out_wakeup:
- task_wakeup(fdtab[fd].owner);
+ task_wakeup(fdtab[fd].owner, TASK_WOKEN_IO);
out_skip_wakeup:
fdtab[fd].ev &= ~FD_POLL_OUT;
diff --git a/src/task.c b/src/task.c
index 5182b81..98967c5 100644
--- a/src/task.c
+++ b/src/task.c
@@ -149,7 +149,8 @@
t->eb.key += offset;
}
- t->state = TASK_RUNNING;
+ /* clear state flags at the same time */
+ t->state = TASK_IN_RUNQUEUE;
eb32_insert(&rqueue[ticks_to_tree(t->eb.key)], &t->eb);
return t;
@@ -229,6 +230,7 @@
/* detach the task from the queue and add the task to the run queue */
eb = eb32_next(eb);
__task_wakeup(task);
+ task->state |= TASK_WOKEN_TIMER;
}
tree = (tree + 1) & TIMER_TREE_MASK;
} while (((tree - now_tree) & TIMER_TREE_MASK) < TIMER_TREES/2);
@@ -286,7 +288,7 @@
run_queue--;
if (likely(t->nice))
niced_tasks--;
- t->state = TASK_IDLE;
+ t->state &= ~TASK_IN_RUNQUEUE;
task_dequeue(t);
t->process(t, &temp);