[Sheepdog] [PATCH v2 09/13] trace: add a ring buffer
Liu Yuan
namei.unix at gmail.com
Thu Feb 16 12:21:28 CET 2012
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)
{
--
1.7.8.2
More information about the sheepdog
mailing list