[MINOR] task: keep a task count and clean up task creators

It's sometimes useful at least for statistics to keep a task count.
It's easy to do by forcing the rare task creators to always use the
same functions to create/destroy a task.
diff --git a/include/proto/task.h b/include/proto/task.h
index 86a3c3d..54418b6 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -78,6 +78,7 @@
 #define TIMER_LOOK_BACK       (1U << 31)
 
 /* a few exported variables */
+extern unsigned int nb_tasks;     /* total number of tasks */
 extern unsigned int run_queue;    /* run queue size */
 extern unsigned int niced_tasks;  /* number of niced tasks in the run queue */
 extern struct pool_head *pool2_task;
@@ -160,8 +161,9 @@
 }
 
 /*
- * Initialize a new task. The bare minimum is performed (queue pointers and state).
- * The task is returned.
+ * Initialize a new task. The bare minimum is performed (queue pointers and
+ * state).  The task is returned. This function should not be used outside of
+ * task_new().
  */
 static inline struct task *task_init(struct task *t)
 {
@@ -173,11 +175,28 @@
 }
 
 /*
- * frees a task. Its context must have been freed since it will be lost.
+ * Allocate and initialise a new task. The new task is returned, or NULL in
+ * case of lack of memory. The task count is incremented. Tasks should only
+ * be allocated this way, and must be freed using task_free().
+ */
+static inline struct task *task_new(void)
+{
+	struct task *t = pool_alloc2(pool2_task);
+	if (t) {
+		nb_tasks++;
+		task_init(t);
+	}
+	return t;
+}
+
+/*
+ * Free a task. Its context must have been freed since it will be lost.
+ * The task count is decremented.
  */
 static inline void task_free(struct task *t)
 {
 	pool_free2(pool2_task, t);
+	nb_tasks--;
 }
 
 /* Place <task> into the wait queue, where it may already be. If the expiration
diff --git a/src/appsession.c b/src/appsession.c
index a1c1c88..754e261 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -87,10 +87,9 @@
 {
 	static int initialized = 0;
 	if (!initialized) {
-		if ((appsess_refresh = pool_alloc2(pool2_task)) == NULL)
+		if ((appsess_refresh = task_new()) == NULL)
 			return -1;
 
-		task_init(appsess_refresh);
 		appsess_refresh->context = NULL;
 		appsess_refresh->expire = tick_add(now_ms, MS_TO_TICKS(TBLCHKINT));
 		appsess_refresh->process = appsession_refresh;
diff --git a/src/checks.c b/src/checks.c
index f1e8120..50b464f 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -837,14 +837,12 @@
 			if (!(s->state & SRV_CHECKED))
 				continue;
 
-			if ((t = pool_alloc2(pool2_task)) == NULL) {
+			if ((t = task_new()) == NULL) {
 				Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
 				return -1;
 			}
 
 			s->check = t;
-
-			task_init(t);
 			t->process = process_chk;
 			t->context = s;
 
diff --git a/src/client.c b/src/client.c
index f5ce3c6..765a54b 100644
--- a/src/client.c
+++ b/src/client.c
@@ -134,7 +134,7 @@
 			s->flags |= SN_MONITOR;
 		}
 
-		if ((t = pool_alloc2(pool2_task)) == NULL) { /* disable this proxy for a while */
+		if ((t = task_new()) == NULL) { /* disable this proxy for a while */
 			Alert("out of memory in event_accept().\n");
 			EV_FD_CLR(fd, DIR_RD);
 			p->state = PR_STIDLE;
@@ -160,7 +160,6 @@
 		if (p->options & PR_O_TCP_NOLING)
 			setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
 
-		task_init(t);
 		t->process = l->handler;
 		t->context = s;
 
@@ -473,7 +472,7 @@
 	pool_free2(p->req_cap_pool, txn->req.cap);
  out_fail_reqcap:
  out_free_task:
-	pool_free2(pool2_task, t);
+	task_free(t);
  out_free_session:
 	LIST_DEL(&s->list);
 	pool_free2(pool2_session, s);
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 1b38774..baf91ef 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -414,7 +414,7 @@
 		s->flags = 0;
 		s->term_trace = 0;
 
-		if ((t = pool_alloc2(pool2_task)) == NULL) {
+		if ((t = task_new()) == NULL) {
 			Alert("out of memory in uxst_event_accept().\n");
 			goto out_free_session;
 		}
@@ -432,7 +432,6 @@
 			goto out_free_task;
 		}
 
-		task_init(t);
 		t->process = l->handler;
 		t->context = s;
 		t->nice = -64;  /* we want to boost priority for local stats */
@@ -550,7 +549,7 @@
  out_free_req:
 	pool_free2(pool2_buffer, s->req);
  out_free_task:
-	pool_free2(pool2_task, t);
+	task_free(t);
  out_free_session:
 	LIST_DEL(&s->list);
 	pool_free2(pool2_session, s);
diff --git a/src/task.c b/src/task.c
index 72e3a93..8374c12 100644
--- a/src/task.c
+++ b/src/task.c
@@ -25,6 +25,7 @@
 
 struct pool_head *pool2_task;
 
+unsigned int nb_tasks = 0;
 unsigned int run_queue = 0;
 unsigned int niced_tasks = 0;      /* number of niced tasks in the run queue */
 struct eb32_node *last_timer = NULL;  /* optimization: last queued timer */