Mesa (master): util: add generic ringbuffer utitilty

Keith Whitwell keithw at kemper.freedesktop.org
Sat Jan 16 21:16:12 UTC 2010


Module: Mesa
Branch: master
Commit: 164fd16cfbc09970676c2e6866e062a5c9b410db
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=164fd16cfbc09970676c2e6866e062a5c9b410db

Author: Keith Whitwell <keithw at vmware.com>
Date:   Sat Jan 16 21:11:01 2010 +0000

util: add generic ringbuffer utitilty

---

 src/gallium/auxiliary/Makefile            |    1 +
 src/gallium/auxiliary/SConscript          |    1 +
 src/gallium/auxiliary/util/u_ringbuffer.c |  145 +++++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_ringbuffer.h |   29 ++++++
 4 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index e3af41c..8f937e3 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -111,6 +111,7 @@ C_SOURCES = \
 	util/u_math.c \
 	util/u_mm.c \
 	util/u_rect.c \
+	util/u_ringbuffer.c \
 	util/u_simple_shaders.c \
 	util/u_snprintf.c \
 	util/u_stream_stdc.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 782eb53..f957090 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -147,6 +147,7 @@ source = [
     'util/u_math.c',
     'util/u_mm.c',
     'util/u_rect.c',
+    'util/u_ringbuffer.c',
     'util/u_simple_shaders.c',
     'util/u_snprintf.c',
     'util/u_stream_stdc.c',
diff --git a/src/gallium/auxiliary/util/u_ringbuffer.c b/src/gallium/auxiliary/util/u_ringbuffer.c
new file mode 100644
index 0000000..3f43a19
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_ringbuffer.c
@@ -0,0 +1,145 @@
+
+#include "pipe/p_thread.h"
+#include "pipe/p_defines.h"
+#include "util/u_ringbuffer.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+/* Generic ringbuffer: 
+ */
+struct util_ringbuffer 
+{
+   struct util_packet *buf;
+   unsigned mask;
+
+   /* Can this be done with atomic variables??
+    */
+   unsigned head;
+   unsigned tail;
+   pipe_condvar change;
+   pipe_mutex mutex;
+};
+
+
+struct util_ringbuffer *util_ringbuffer_create( unsigned dwords )
+{
+   struct util_ringbuffer *ring = CALLOC_STRUCT(util_ringbuffer);
+   if (ring == NULL)
+      return NULL;
+
+   assert(util_is_power_of_two(dwords));
+   
+   ring->buf = MALLOC( dwords * sizeof(unsigned) );
+   if (ring->buf == NULL)
+      goto fail;
+
+   ring->mask = dwords - 1;
+
+   pipe_condvar_init(ring->change);
+   pipe_mutex_init(ring->mutex);
+   return ring;
+
+fail:
+   FREE(ring->buf);
+   FREE(ring);
+   return NULL;
+}
+
+void util_ringbuffer_destroy( struct util_ringbuffer *ring )
+{
+   pipe_condvar_destroy(ring->change);
+   pipe_mutex_destroy(ring->mutex);
+   FREE(ring->buf);
+   FREE(ring);
+}
+
+static INLINE unsigned util_ringbuffer_space( const struct util_ringbuffer *ring )
+{
+   return (ring->tail - (ring->head + 1)) & ring->mask;
+}
+
+void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
+                              const struct util_packet *packet )
+{
+   unsigned i;
+
+   /* XXX: over-reliance on mutexes, etc:
+    */
+   pipe_mutex_lock(ring->mutex);
+
+   /* Wait for free space:
+    */
+   while (util_ringbuffer_space(ring) < packet->dwords)
+      pipe_condvar_wait(ring->change, ring->mutex);
+
+   /* Copy data to ring:
+    */
+   for (i = 0; i < packet->dwords; i++) {
+
+      /* Copy all dwords of the packet.  Note we're abusing the
+       * typesystem a little - we're being passed a pointer to
+       * something, but probably not an array of packet structs:
+       */
+      ring->buf[ring->head] = packet[i];
+      ring->head++;
+      ring->head &= ring->mask;
+   }
+
+   /* Signal change:
+    */
+   pipe_condvar_signal(ring->change);
+   pipe_mutex_unlock(ring->mutex);
+}
+
+enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
+                                         struct util_packet *packet,
+                                         unsigned max_dwords,
+                                         boolean wait )
+{
+   const struct util_packet *ring_packet;
+   unsigned i;
+   int ret = PIPE_OK;
+
+   /* XXX: over-reliance on mutexes, etc:
+    */
+   pipe_mutex_lock(ring->mutex);
+
+   /* Wait for free space:
+    */
+   if (wait) {
+      while (util_ringbuffer_space(ring) == 0)
+         pipe_condvar_wait(ring->change, ring->mutex);
+   }
+   else {
+      if (util_ringbuffer_space(ring) == 0) {
+         ret = PIPE_ERROR_OUT_OF_MEMORY;
+         goto out;
+      }
+   }
+
+   ring_packet = &ring->buf[ring->tail];
+
+   /* Both of these are considered bugs.  Raise an assert on debug builds.
+    */
+   if (ring_packet->dwords > ring->mask + 1 - util_ringbuffer_space(ring) ||
+       ring_packet->dwords > max_dwords) {
+      assert(0);
+      ret = PIPE_ERROR_BAD_INPUT;
+      goto out;
+   }
+
+   /* Copy data from ring:
+    */
+   for (i = 0; i < ring_packet->dwords; i++) {
+      packet[i] = ring->buf[ring->tail];
+      ring->tail++;
+      ring->tail &= ring->mask;
+   }
+
+out:
+   /* Signal change:
+    */
+   pipe_condvar_signal(ring->change);
+   pipe_mutex_unlock(ring->mutex);
+   return ret;
+}
diff --git a/src/gallium/auxiliary/util/u_ringbuffer.h b/src/gallium/auxiliary/util/u_ringbuffer.h
new file mode 100644
index 0000000..85f0ad6
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_ringbuffer.h
@@ -0,0 +1,29 @@
+
+#ifndef UTIL_RINGBUFFER_H
+#define UTIL_RINGBUFFER_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_defines.h"       /* only for pipe_error! */
+
+/* Generic header
+ */
+struct util_packet {
+   unsigned dwords:8;
+   unsigned data24:24;
+};
+
+struct util_ringbuffer;
+
+struct util_ringbuffer *util_ringbuffer_create( unsigned dwords );
+
+void util_ringbuffer_destroy( struct util_ringbuffer *ring );
+
+void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
+                              const struct util_packet *packet );
+
+enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
+                                         struct util_packet *packet,
+                                         unsigned max_dwords,
+                                         boolean wait );
+
+#endif




More information about the mesa-commit mailing list