[MEDIUM] listeners: queue proxy-bound listeners at the proxy's

All listeners that are limited by a proxy-specific resource are now
queued at the proxy's and not globally. This allows finer-grained
wakeups when releasing resource.
diff --git a/src/stream_sock.c b/src/stream_sock.c
index fa03a62..a0b2c11 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1192,7 +1192,6 @@
 	int max_accept = global.tune.maxaccept;
 	int cfd;
 	int ret;
-	int loops = 0;
 
 	if (unlikely(l->nbconn >= l->maxconn)) {
 		listener_full(l);
@@ -1201,15 +1200,31 @@
 
 	if (p && p->fe_sps_lim) {
 		int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
+
+		if (unlikely(!max)) {
+			/* frontend accept rate limit was reached */
+			limit_listener(l, &p->listener_queue);
+			return 0;
+		}
+
 		if (max_accept > max)
 			max_accept = max;
 	}
 
-	while ((!p || p->feconn < p->maxconn) && actconn < global.maxconn && max_accept--) {
+	while (max_accept--) {
 		struct sockaddr_storage addr;
 		socklen_t laddr = sizeof(addr);
 
+		if (unlikely(actconn >= global.maxconn)) {
+			limit_listener(l, &global_listener_queue);
+			return 0;
+		}
+
+		if (unlikely(p && p->feconn >= p->maxconn)) {
+			limit_listener(l, &p->listener_queue);
+			return 0;
+		}
+
-		loops++;
 		cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
 		if (unlikely(cfd == -1)) {
 			switch (errno) {
@@ -1287,10 +1302,6 @@
 
 	} /* end of while (p->feconn < p->maxconn) */
 
-	/* if we did not even enter the loop, we've reached resource limits */
-	if (!loops && max_accept)
-		limit_listener(l, &global_listener_queue);
-
 	return 0;
 }