From: Liu Yuan <tailai.ly at taobao.com> Tracers use this ring buffer to store its output internally. 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 45e99e8..d9e8429 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 rbtree.c +libsheepdog_a_SOURCES = event.c logger.c net.c util.c coroutine.c rbtree.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 db173df..94a4f71 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) { -- 1.7.8.2 |