[systemd-devel] [RFC 02/12] ring: add basic ring-buffer helper

Lucas De Marchi lucas.de.marchi at gmail.com
Wed Nov 27 16:27:06 PST 2013


On Wed, Nov 27, 2013 at 4:48 PM, David Herrmann <dh.herrmann at gmail.com> wrote:
> This adds a very straightforward ring-buffer implementation to
> libsystemd-shared. Ring-buffers allow pushing data to, and pulling data
> from, both ends of a buffer without modifying existing/remaining buffer
> content. This is very useful for network buffers and asynchronous writes.
>
> This implementation only contains the most basic functions to push data
> onto the end of the buffer and pull data from the front. More helpers may
> be added once needed.
> ---
>  Makefile.am       |   2 +
>  src/shared/ring.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/shared/ring.h |  54 ++++++++++++++
>  3 files changed, 269 insertions(+)
>  create mode 100644 src/shared/ring.c
>  create mode 100644 src/shared/ring.h
>
> diff --git a/Makefile.am b/Makefile.am
> index 0119751..4aa2bdf 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -768,6 +768,8 @@ libsystemd_shared_la_SOURCES = \
>         src/shared/net-util.h \
>         src/shared/errno-list.c \
>         src/shared/errno-list.h \
> +       src/shared/ring.h \
> +       src/shared/ring.c \
>         src/shared/syscall-list.c \
>         src/shared/syscall-list.h
>
> diff --git a/src/shared/ring.c b/src/shared/ring.c
> new file mode 100644
> index 0000000..f60f098
> --- /dev/null
> +++ b/src/shared/ring.c
> @@ -0,0 +1,213 @@
> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
> +
> +/***
> +  This file is part of systemd.
> +
> +  Copyright 2013 David Herrmann <dh.herrmann at gmail.com>
> +
> +  systemd is free software; you can redistribute it and/or modify it
> +  under the terms of the GNU Lesser General Public License as published by
> +  the Free Software Foundation; either version 2.1 of the License, or
> +  (at your option) any later version.
> +
> +  systemd is distributed in the hope that it will be useful, but
> +  WITHOUT ANY WARRANTY; without even the implied warranty of
> +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +  Lesser General Public License for more details.
> +
> +  You should have received a copy of the GNU Lesser General Public License
> +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +***/
> +
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/uio.h>
> +
> +#include "ring.h"
> +#include "util.h"
> +
> +#define RING_MASK(_r, _v) ((_v) & ((_r)->size - 1))
> +
> +void ring_flush(Ring *r) {
> +        r->start = 0;
> +        r->end = 0;
> +}
> +
> +void ring_clear(Ring *r) {
> +        free(r->buf);
> +        memset(r, 0, sizeof(*r));
> +}
> +
> +/*
> + * Resize ring-buffer to size @nsize. @nsize must be a power-of-2, otherwise
> + * ring operations will behave incorrectly.
> + */
> +static int ring_resize(Ring *r, size_t nsize) {
> +        char *buf;
> +
> +        buf = malloc(nsize);
> +        if (!buf)
> +                return -ENOMEM;
> +
> +        if (r->end == r->start) {
> +                r->end = 0;
> +                r->start = 0;
> +        } else if (r->end > r->start) {
> +                memcpy(buf, &r->buf[r->start], r->end - r->start);
> +
> +                r->end -= r->start;
> +                r->start = 0;
> +        } else {
> +                memcpy(buf, &r->buf[r->start], r->size - r->start);
> +                memcpy(&buf[r->size - r->start], r->buf, r->end);
> +
> +                r->end += r->size - r->start;
> +                r->start = 0;
> +        }
> +
> +        free(r->buf);
> +        r->buf = buf;
> +        r->size = nsize;
> +
> +        return 0;
> +}
> +
> +/* Compute next higher power-of-2 of @v. Returns 4096 in case v is 0. */
> +static size_t ring_pow2(size_t v) {
> +        size_t i;
> +
> +        if (!v)
> +                return 4096;
> +
> +        --v;
> +
> +        for (i = 1; i < 8 * sizeof(size_t); i *= 2)
> +                v |= v >> i;
> +
> +        return ++v;

If you are interested, take a look in
https://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/?id=3ba7f59e84857eb4dbe56a68fc7a3ffe8a650393
for a shorter and faster version of this.


Lucas De Marchi


More information about the systemd-devel mailing list