REORG: listener: move the global listener queue code to listener.c

The global listener queue code and declarations were still lying in
haproxy.c while not needed there anymore at all. This complicates
the code for no reason. As a result, the global_listener_queue_task
and the global_listener_queue were made static.
diff --git a/src/listener.c b/src/listener.c
index 848b01e..94200c7 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -55,6 +55,12 @@
  */
 static struct work_list *local_listener_queue;
 
+/* list of the temporarily limited listeners because of lack of resource */
+static struct mt_list global_listener_queue = MT_LIST_HEAD_INIT(global_listener_queue);
+static struct task *global_listener_queue_task;
+static struct task *manage_global_listener_queue(struct task *t, void *context, unsigned short state);
+
+
 #if defined(USE_THREAD)
 
 struct accept_queue_ring accept_queue_rings[MAX_THREADS] __attribute__((aligned(64))) = { };
@@ -1144,17 +1150,57 @@
 		ha_alert("Out of memory while initializing listener queues.\n");
 		return ERR_FATAL|ERR_ABORT;
 	}
+
+	global_listener_queue_task = task_new(MAX_THREADS_MASK);
+	if (!global_listener_queue_task) {
+		ha_alert("Out of memory when initializing global listener queue\n");
+		return ERR_FATAL|ERR_ABORT;
+	}
+	/* very simple initialization, users will queue the task if needed */
+	global_listener_queue_task->context = NULL; /* not even a context! */
+	global_listener_queue_task->process = manage_global_listener_queue;
+
 	return 0;
 }
 
 static void listener_queue_deinit()
 {
 	work_list_destroy(local_listener_queue, global.nbthread);
+	task_destroy(global_listener_queue_task);
+	global_listener_queue_task = NULL;
 }
 
 REGISTER_CONFIG_POSTPARSER("multi-threaded listener queue", listener_queue_init);
 REGISTER_POST_DEINIT(listener_queue_deinit);
 
+
+/* This is the global management task for listeners. It enables listeners waiting
+ * for global resources when there are enough free resource, or at least once in
+ * a while. It is designed to be called as a task.
+ */
+static struct task *manage_global_listener_queue(struct task *t, void *context, unsigned short state)
+{
+	/* If there are still too many concurrent connections, let's wait for
+	 * some of them to go away. We don't need to re-arm the timer because
+	 * each of them will scan the queue anyway.
+	 */
+	if (unlikely(actconn >= global.maxconn))
+		goto out;
+
+	/* We should periodically try to enable listeners waiting for a global
+	 * resource here, because it is possible, though very unlikely, that
+	 * they have been blocked by a temporary lack of global resource such
+	 * as a file descriptor or memory and that the temporary condition has
+	 * disappeared.
+	 */
+	dequeue_all_listeners();
+
+ out:
+	t->expire = TICK_ETERNITY;
+	task_queue(t);
+	return t;
+}
+
 /*
  * Registers the bind keyword list <kwl> as a list of valid keywords for next
  * parsing sessions.