[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);