[Sheepdog] [PATCH v2 09/13] trace: add a ring buffer

Steven Dake sdake at redhat.com
Thu Feb 16 16:40:55 CET 2012


Have a look at the ring buffer in libqb.  (http://www.libqb.org).  It
allows arbitrary sized ring buffers with arbitrary sized blocks of data
(rather then pointers as in this implementation).

There is also tracing/logging in this library, but you may be more
interested in the on/off model vs the always-on model imposed by libqb.
 (Even though the always-on model is very low overhead).

Regards
-steve


On 02/16/2012 04:21 AM, Liu Yuan wrote:
> From: Liu Yuan <tailai.ly at taobao.com>
> 
> 
> Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
> ---
>  include/util.h      |   24 ++++++++++++++++++++++
>  lib/Makefile.am     |    2 +-
>  lib/ring_buffer.c   |   54 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  sheep/trace/graph.c |    2 +
>  4 files changed, 81 insertions(+), 1 deletions(-)
>  create mode 100644 lib/ring_buffer.c
> 
> diff --git a/include/util.h b/include/util.h
> index ff86a00..ca43ab9 100644
> --- a/include/util.h
> +++ b/include/util.h
> @@ -6,6 +6,7 @@
>  #include <stdint.h>
>  
>  #include "bitops.h"
> +#include "list.h"
>  
>  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
>  #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
> @@ -69,4 +70,27 @@ extern ssize_t xwrite(int fd, const void *buf, size_t len);
>  extern ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
>  extern ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
>  
> +/* ring_buffer.c */
> +struct rbuffer {
> +	struct list_head list;
> +	char *buffer;           /* data buffer */
> +	char *buffer_end;
> +	size_t capacity;        /* initial maximum number of items in the buffer */
> +	size_t count;           /* number of items in the buffer */
> +	size_t sz;              /* size of each item in the buffer */
> +	char *head;
> +	char *tail;
> +};
> +
> +static inline size_t rbuffer_size(struct rbuffer *rbuf)
> +{
> +	return rbuf->count * rbuf->sz;
> +}
> +
> +void rbuffer_push(struct rbuffer *rbuf, const void *item);
> +void rbuffer_pop(struct rbuffer *rbuf, void *item);
> +void rbuffer_destroy(struct rbuffer *rbuf);
> +void rbuffer_create(struct rbuffer *rbuf, size_t capacity, size_t item_size);
> +void rbuffer_reset(struct rbuffer *rbuf);
> +
>  #endif
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index c4fb3af..fe41ad0 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -4,4 +4,4 @@ INCLUDES                = -I$(top_builddir)/include -I$(top_srcdir)/include
>  
>  noinst_LIBRARIES	= libsheepdog.a
>  
> -libsheepdog_a_SOURCES	= event.c logger.c net.c util.c coroutine.c
> +libsheepdog_a_SOURCES	= event.c logger.c net.c util.c coroutine.c ring_buffer.c
> diff --git a/lib/ring_buffer.c b/lib/ring_buffer.c
> new file mode 100644
> index 0000000..a37d6c7
> --- /dev/null
> +++ b/lib/ring_buffer.c
> @@ -0,0 +1,54 @@
> +#include <pthread.h>
> +#include <stdlib.h>
> +
> +#include "util.h"
> +#include "logger.h"
> +
> +notrace void rbuffer_create(struct rbuffer *rbuf, size_t capacity, size_t sz)
> +{
> +	rbuf->buffer = xmalloc(capacity * sz);
> +	rbuf->buffer_end = rbuf->buffer + capacity * sz;
> +	rbuf->capacity = capacity;
> +	rbuf->count = 0;
> +	rbuf->sz = sz;
> +	rbuf->head = rbuf->tail = rbuf->buffer;
> +}
> +
> +notrace void rbuffer_destroy(struct rbuffer *rbuf)
> +{
> +	free(rbuf->buffer);
> +}
> +
> +notrace void rbuffer_reset(struct rbuffer *rbuf)
> +{
> +	rbuf->count = 0;
> +	rbuf->head = rbuf->tail = rbuf->buffer;
> +}
> +
> +/* Push the item to the tail of the buffer */
> +notrace void rbuffer_push(struct rbuffer *rbuf, const void *item)
> +{
> +	if (rbuf->count == rbuf->capacity) {
> +		dprintf("buffer full\n");
> +		return;
> +	}
> +	memcpy(rbuf->tail, item, rbuf->sz);
> +	rbuf->tail += rbuf->sz;
> +	if (rbuf->tail == rbuf->buffer_end)
> +		rbuf->tail = rbuf->buffer;
> +	rbuf->count++;
> +}
> +
> +/* Push the item from the head of the buffer */
> +notrace void rbuffer_pop(struct rbuffer *rbuf, void *item)
> +{
> +	if (rbuf->count == 0) {
> +		dprintf("no item left\n");
> +		return;
> +	}
> +	memcpy(item, rbuf->head, rbuf->sz);
> +	rbuf->head += rbuf->sz;
> +	if (rbuf->head == rbuf->buffer_end)
> +		rbuf->head = rbuf->buffer;
> +	rbuf->count--;
> +}
> diff --git a/sheep/trace/graph.c b/sheep/trace/graph.c
> index 7dfafc8..58094a3 100644
> --- a/sheep/trace/graph.c
> +++ b/sheep/trace/graph.c
> @@ -12,6 +12,8 @@ static __thread struct trace_ret_stack {
>  	unsigned long long entry_time;
>  } trace_ret_stack[100]; /* FIXME: consider stack overrun */
>  
> +static __thread struct rbuffer rbuf;
> +
>  static void push_return_trace(unsigned long ret, unsigned long long etime,
>  		unsigned long func, int *depth)
>  {




More information about the sheepdog mailing list