server: use ringbuffer for all handlers

Currently, we use the a ringbuffer within the socket handler to manage
bursts of data to slower clients.

However, we're also seeing cases where the local tty handler becomes
blocking as well. So, we want to implement a buffer within the tty
handler too.

This change moves the ringbuffer 'up a layer' - from the socket handler
to the core console code.

We remove the ->data_in callback from handlers, and work on the
assumption that handlers have registered their own consumer on the
console's ringbuffer (through a new helper function,
console_ringbuffer_consumer_register()).

Change-Id: Ie8f02d6632578c50bb5e2dfb9bee6ece86432135
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/console-server.c b/console-server.c
index 0ed358d..e8f0352 100644
--- a/console-server.c
+++ b/console-server.c
@@ -46,6 +46,8 @@
 	int		tty_lpc_addr;
 	int		tty_fd;
 
+	struct ringbuffer	*rb;
+
 	struct handler	**handlers;
 	int		n_handlers;
 
@@ -65,6 +67,9 @@
 /* we have one extra entry in the pollfds array for the VUART tty */
 static const int n_internal_pollfds = 1;
 
+/* size of the shared backlog ringbuffer */
+const size_t buffer_size = 128 * 1024;
+
 /* state shared with the signal handler */
 static bool sigint;
 
@@ -311,29 +316,11 @@
 	}
 }
 
-static int handlers_data_in(struct console *console, uint8_t *buf, size_t len)
+struct ringbuffer_consumer *console_ringbuffer_consumer_register(
+		struct console *console,
+		ringbuffer_poll_fn_t poll_fn, void *data)
 {
-	struct handler *handler;
-	int i, rc, tmp;
-
-	rc = 0;
-
-	for (i = 0; i < console->n_handlers; i++) {
-		handler = console->handlers[i];
-
-		if (!handler->active)
-			continue;
-
-		if (!handler->data_in)
-			continue;
-
-		tmp = handler->data_in(handler, buf, len);
-		if (tmp == HANDLER_EXIT)
-			rc = 1;
-	}
-
-	return rc;
-
+	return ringbuffer_consumer_register(console->rb, poll_fn, data);
 }
 
 struct poller *console_poller_register(struct console *console,
@@ -501,7 +488,7 @@
 				rc = -1;
 				break;
 			}
-			rc = handlers_data_in(console, buf, rc);
+			rc = ringbuffer_queue(console->rb, buf, rc);
 			if (rc)
 				break;
 		}
@@ -561,6 +548,7 @@
 	memset(console, 0, sizeof(*console));
 	console->pollfds = calloc(n_internal_pollfds,
 			sizeof(*console->pollfds));
+	console->rb = ringbuffer_init(buffer_size);
 
 	config = config_init(config_filename);
 	if (!config) {