server: Use ringbuffer for socket backlog
Currently, the socket handler uses a linear buffer for the backlog data;
this means we need to shift up to 128kB of data after each socket
write().
This change introduces a single-producer-multiple-consumer ringbuffer,
to avoid the need for memmove()ing data around; we can simply update
pointers instead of shifting data.
We add this as a new file (ringbuffer.c), to make it a little more
modular. To mitigate the risk of subtle pointer arithmetic issues, we
add a set of tests too.
Change-Id: Ib7c5151d3cf1f588436f5461000b6fed22d0681c
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/test/test-ringbuffer-poll-force.c b/test/test-ringbuffer-poll-force.c
new file mode 100644
index 0000000..0993de5
--- /dev/null
+++ b/test/test-ringbuffer-poll-force.c
@@ -0,0 +1,48 @@
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "ringbuffer.c"
+#include "ringbuffer-test-utils.c"
+
+void test_poll_force(void)
+{
+ uint8_t in_buf[] = { 'a', 'b', 'c', 'd', 'e', 'f', };
+ struct rb_test_ctx _ctx, *ctx = &_ctx;
+ struct ringbuffer *rb;
+ int rc;
+
+ ringbuffer_test_context_init(ctx);
+
+ rb = ringbuffer_init(5);
+
+ ctx->rbc = ringbuffer_consumer_register(rb,
+ ringbuffer_poll_append_all, ctx);
+
+ ctx->force_only = true;
+
+ /* fill the ringbuffer */
+ rc = ringbuffer_queue(rb, in_buf, 4);
+ assert(!rc);
+
+ assert(ctx->count == 0);
+
+ /* add more data */
+ rc = ringbuffer_queue(rb, in_buf + 4, 2);
+ assert(!rc);
+
+ /* we should have had a forced poll for the initial two bytes */
+ assert(ctx->count == 1);
+ assert(ctx->len == 2);
+ assert(!memcmp(in_buf, ctx->data, 2));
+
+ ringbuffer_fini(rb);
+ ringbuffer_test_context_fini(ctx);
+}
+
+int main(void)
+{
+ test_poll_force();
+ return EXIT_SUCCESS;
+}