]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
s/cbuff/fring/
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Jun 2017 19:45:09 +0000 (15:45 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Jun 2017 19:55:13 +0000 (15:55 -0400)
src/include/debug.h
src/include/fring.h [moved from src/include/cbuff.h with 73% similarity]
src/lib/util/all.mk
src/lib/util/cbuff.c [deleted file]
src/lib/util/debug.c
src/lib/util/fring.c [new file with mode: 0644]

index 373538d36c69f675cb4cec6bed9772b550cd5add..e9dd33c7f50466ea7536766ae77a7d91ff2d6ae0 100644 (file)
@@ -23,7 +23,7 @@
  *
  * @copyright 2015-2017 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
  */
-#include <freeradius-devel/cbuff.h>
+#include <freeradius-devel/fring.h>
 
 typedef enum {
        DEBUGGER_STATE_UNKNOWN_NO_PTRACE        = -3,   //!< We don't have ptrace so can't check.
@@ -55,9 +55,9 @@ typedef struct fr_bt_marker fr_bt_marker_t;
 void           fr_debug_state_store(void);
 char const     *fr_debug_state_to_msg(fr_debug_state_t state);
 void           fr_debug_break(bool always);
-void           backtrace_print(fr_cbuff_t *cbuff, void *obj);
+void           backtrace_print(fr_fring_t *fring, void *obj);
 int            fr_backtrace_do(fr_bt_marker_t *marker);
-fr_bt_marker_t *fr_backtrace_attach(fr_cbuff_t **cbuff, TALLOC_CTX *obj);
+fr_bt_marker_t *fr_backtrace_attach(fr_fring_t **fring, TALLOC_CTX *obj);
 
 void           fr_panic_on_free(TALLOC_CTX *ctx);
 int            fr_set_dumpable_init(void);
similarity index 73%
rename from src/include/cbuff.h
rename to src/include/fring.h
index 2e1c17b7edc073e90ce7a4d4d7641bbc6dc85d58..31807ff571332dcad0f36adc6d214f60db61f946 100644 (file)
 /*
  * $Id$
  *
- * @file include/cbuff.h
- * @brief Simple circular buffer for debugging purposes.
+ * @file include/fring_buffer.h
+ * @brief Simple ring buffer with fixed element sizes.
  *
  * @copyright 2015-2017 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
  */
 #include <stdbool.h>
 #include <stdint.h>
 
-typedef struct fr_cbuff fr_cbuff_t;
+typedef struct fr_fring_buffer fr_fring_t;
 
-fr_cbuff_t     *fr_cbuff_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock);
-void           fr_cbuff_insert(fr_cbuff_t *cbuff, void *obj);
-void           *fr_cbuff_next(fr_cbuff_t *cbuff);
+fr_fring_t     *fr_fring_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock);
+int                    fr_fring_overwrite(fr_fring_t *fring, void *obj);
+int                    fr_fring_insert(fr_fring_t *fring, void *obj);
+void                   *fr_fring_next(fr_fring_t *fring);
 #endif /* _FR_CBUFF_H */
index bc38993bbde058454032e347852f7caf8fddcae1..298e0e6827c22429d9d62a2361fb5a308f369708 100644 (file)
@@ -6,13 +6,13 @@
 TARGET         := libfreeradius-util.a
 
 SOURCES                := base64.c \
-                  cbuff.c \
                   cursor.c \
                   debug.c \
                   dict.c \
                   event.c \
                   fifo.c \
                   filters.c \
+                  fring.c \
                   getaddrinfo.c \
                   hash.c \
                   heap.c \
diff --git a/src/lib/util/cbuff.c b/src/lib/util/cbuff.c
deleted file mode 100644 (file)
index d086044..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program 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 General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-/**
- * @file lib/util/cbuff.c
- * @brief Implementation of a ring buffer
- *
- * @copyright 2013  The FreeRADIUS server project
- * @copyright 2013  Arran Cudbard-Bell <a.cudbardb@freeradius.org>
- */
-RCSID("$Id$")
-
-#include <freeradius-devel/libradius.h>
-#include <pthread.h>
-
-/** Standard thread safe circular buffer
- *
- */
-struct fr_cbuff {
-       void const              *end;                   //!< End of allocated memory
-
-       uint32_t                size;
-       uint32_t                in;                     //!< Write index
-       uint32_t                out;                    //!< Read index
-
-       void                    **data;                 //!< Ring buffer data
-
-       bool                    lock;                   //!< Perform thread synchronisation
-
-       pthread_mutex_t         mutex;                  //!< Thread synchronisation mutex
-};
-
-/** Destroy mutex associated with circular buffer
- *
- * @param[in] cbuff being freed.
- * @return 0
- */
-static int _cbuff_free(fr_cbuff_t *cbuff)
-{
-       void *next;
-
-       if (cbuff->lock) pthread_mutex_destroy(&cbuff->mutex);
-
-       /*
-        *      Free any data left in the buffer
-        */
-       while ((next = fr_cbuff_next(cbuff))) talloc_free(next);
-
-       return 0;
-}
-
-/** Initialise a new circular buffer
- *
- * @param[in] ctx      to allocate the buffer in.
- * @param[in] size     of buffer to allocate.
- * @param[in] lock     If true, insert and next operations will lock the buffer.
- * @return
- *     - New cbuff.
- *     - NULL on error.
- */
-fr_cbuff_t *fr_cbuff_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock)
-{
-       fr_cbuff_t *cbuff;
-
-       uint32_t pow;
-
-       /*
-        *      Find the nearest power of 2 (rounding up)
-        */
-       for (pow = 0x00000001;
-            pow < size;
-            pow <<= 1);
-       size = pow;
-       size--;
-
-       cbuff = talloc_zero(ctx, fr_cbuff_t);
-       if (!cbuff) return NULL;
-       talloc_set_destructor(cbuff, _cbuff_free);
-
-       cbuff->data = talloc_zero_array(cbuff, void *, size);
-       if (!cbuff->data) {
-               talloc_free(cbuff);
-               return NULL;
-       }
-       cbuff->size = size;
-
-       if (lock) {
-               cbuff->lock = true;
-               pthread_mutex_init(&cbuff->mutex, NULL);
-       }
-
-       return cbuff;
-}
-
-/** Insert a new item into the circular buffer
- *
- * cbuff will steal obj and insert it into it's own context.
- *
- * @param[in] cbuff    to insert item into
- * @param[in] in       item to insert (must have been allocated with talloc).
- */
-void fr_cbuff_insert(fr_cbuff_t *cbuff, void *in)
-{
-       if (cbuff->lock) pthread_mutex_lock(&cbuff->mutex);
-
-       if (cbuff->data[cbuff->in]) talloc_free(cbuff->data[cbuff->in]);
-
-       cbuff->data[cbuff->in] = in;
-       cbuff->in = (cbuff->in + 1) & cbuff->size;
-
-       /* overwrite - out is advanced ahead of in */
-       if (cbuff->in == cbuff->out) cbuff->out = (cbuff->out + 1) & cbuff->size;
-
-       if (cbuff->lock) pthread_mutex_unlock(&cbuff->mutex);
-}
-
-/** Remove an item from the buffer
- *
- * @param[in] cbuff    to drain data from.
- * @return
- *     - NULL if no dataents in the buffer.
- *     - An dataent from the buffer reparented to ctx.
- */
-void *fr_cbuff_next(fr_cbuff_t *cbuff)
-{
-       void *out = NULL;
-
-       if (cbuff->lock) pthread_mutex_lock(&cbuff->mutex);
-
-       /* Buffer is empty */
-       if (cbuff->out == cbuff->in) goto done;
-
-       out = cbuff->data[cbuff->out];
-       cbuff->data[cbuff->out] = NULL;
-       cbuff->out = (cbuff->out + 1) & cbuff->size;
-
-done:
-       if (cbuff->lock) pthread_mutex_unlock(&cbuff->mutex);
-
-       return out;
-}
index 9d7cfbfd5ee9336fdd3555b592b298fd7b8567b7..ff02c29d801b917fe1e98b6f9f0d8adf5754c958 100644 (file)
@@ -77,7 +77,7 @@ typedef struct fr_bt_info {
 struct fr_bt_marker {
        void            *obj;                           //!< Pointer to the parent object, this is our needle
                                                        //!< when we iterate over the contents of the circular buffer.
-       fr_cbuff_t      *cbuff;                         //!< Where we temporarily store the backtraces
+       fr_fring_t      *fring;                         //!< Where we temporarily store the backtraces
 };
 #endif
 
@@ -311,15 +311,15 @@ void fr_debug_break(bool always)
 #ifdef HAVE_EXECINFO
 /** Print backtrace entry for a given object
  *
- * @param cbuff to search in.
+ * @param fring to search in.
  * @param obj pointer to original object
  */
-void backtrace_print(fr_cbuff_t *cbuff, void *obj)
+void backtrace_print(fr_fring_t *fring, void *obj)
 {
        fr_bt_info_t *p;
        bool found = false;
 
-       while ((p = fr_cbuff_next(cbuff))) {
+       while ((p = fr_fring_next(fring))) {
                if ((p->obj == obj) || !obj) {
                        found = true;
 
@@ -341,7 +341,7 @@ int fr_backtrace_do(fr_bt_marker_t *marker)
 {
        fr_bt_info_t *bt;
 
-       if (!fr_cond_assert(marker->obj) || !fr_cond_assert(marker->cbuff)) return -1;
+       if (!fr_cond_assert(marker->obj) || !fr_cond_assert(marker->fring)) return -1;
 
        bt = talloc_zero(NULL, fr_bt_info_t);
        if (!bt) return -1;
@@ -349,7 +349,7 @@ int fr_backtrace_do(fr_bt_marker_t *marker)
        bt->obj = marker->obj;
        bt->count = backtrace(bt->frames, MAX_BT_FRAMES);
 
-       fr_cbuff_insert(marker->cbuff, bt);
+       fr_fring_overwrite(marker->fring, bt);
 
        return 0;
 }
@@ -360,8 +360,8 @@ int fr_backtrace_do(fr_bt_marker_t *marker)
  *
  * Code augmentation should look something like:
 @verbatim
-       // Create a static cbuffer pointer, the first call to backtrace_attach will initialise it
-       static fr_cbuff_t *my_obj_bt;
+       // Create a static fringer pointer, the first call to backtrace_attach will initialise it
+       static fr_fring_t *my_obj_bt;
 
        my_obj_t *alloc_my_obj(TALLOC_CTX *ctx) {
                my_obj_t *this;
@@ -383,17 +383,17 @@ int fr_backtrace_do(fr_bt_marker_t *marker)
  * which should print a limited backtrace to stderr. Note, this backtrace will not include any argument
  * values, but should at least show the code path taken.
  *
- * @param cbuff this should be a pointer to a static *fr_cbuff.
+ * @param fring this should be a pointer to a static *fr_fring_buffer.
  * @param obj we want to generate a backtrace for.
  */
-fr_bt_marker_t *fr_backtrace_attach(fr_cbuff_t **cbuff, TALLOC_CTX *obj)
+fr_bt_marker_t *fr_backtrace_attach(fr_fring_t **fring, TALLOC_CTX *obj)
 {
        fr_bt_marker_t *marker;
 
-       if (*cbuff == NULL) {
+       if (*fring == NULL) {
                pthread_mutex_lock(&fr_debug_init);
                /* Check again now we hold the mutex - eww*/
-               if (*cbuff == NULL) *cbuff = fr_cbuff_alloc(NULL, MAX_BT_CBUFF, true);
+               if (*fring == NULL) *fring = fr_fring_alloc(NULL, MAX_BT_CBUFF, true);
                pthread_mutex_unlock(&fr_debug_init);
        }
 
@@ -403,7 +403,7 @@ fr_bt_marker_t *fr_backtrace_attach(fr_cbuff_t **cbuff, TALLOC_CTX *obj)
        }
 
        marker->obj = (void *) obj;
-       marker->cbuff = *cbuff;
+       marker->fring = *fring;
 
        fprintf(stderr, "Backtrace attached to %s %p\n", talloc_get_name(obj), obj);
        /*
@@ -415,11 +415,11 @@ fr_bt_marker_t *fr_backtrace_attach(fr_cbuff_t **cbuff, TALLOC_CTX *obj)
        return marker;
 }
 #else
-void backtrace_print(UNUSED fr_cbuff_t *cbuff, UNUSED void *obj)
+void backtrace_print(UNUSED fr_fring_t *fring, UNUSED void *obj)
 {
        fprintf(stderr, "Server built without fr_backtrace_* support, requires execinfo.h and possibly -lexecinfo\n");
 }
-fr_bt_marker_t *fr_backtrace_attach(UNUSED fr_cbuff_t **cbuff, UNUSED TALLOC_CTX *obj)
+fr_bt_marker_t *fr_backtrace_attach(UNUSED fr_fring_t **fring, UNUSED TALLOC_CTX *obj)
 {
        fprintf(stderr, "Server built without fr_backtrace_* support, requires execinfo.h and possibly -lexecinfo\n");
        abort();
diff --git a/src/lib/util/fring.c b/src/lib/util/fring.c
new file mode 100644 (file)
index 0000000..1cb2313
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file lib/util/fring.c
+ * @brief Implementation of a circular buffer with fixed element size.
+ *
+ * This offers similar functionality to ring_buffer.c, but uses a fixed
+ * element size, and expects all elements to be talloced.
+ *
+ * @copyright 2013  The FreeRADIUS server project
+ * @copyright 2013  Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/libradius.h>
+#include <pthread.h>
+
+/** Standard thread safe circular buffer
+ *
+ */
+struct fr_fring_buffer {
+       void const              *end;                   //!< End of allocated memory
+
+       uint32_t                size;
+       uint32_t                in;                     //!< Write index
+       uint32_t                out;                    //!< Read index
+
+       void                    **data;                 //!< Ring buffer data
+
+       bool                    lock;                   //!< Perform thread synchronisation
+
+       pthread_mutex_t         mutex;                  //!< Thread synchronisation mutex
+};
+
+/** Destroy mutex associated with ring buffer
+ *
+ * @param[in] fring being freed.
+ * @return 0
+ */
+static int _fring_free(fr_fring_t *fring)
+{
+       void *next;
+
+       if (fring->lock) pthread_mutex_destroy(&fring->mutex);
+
+       /*
+        *      Free any data left in the buffer
+        */
+       while ((next = fr_fring_next(fring))) talloc_free(next);
+
+       return 0;
+}
+
+/** Initialise a ring buffer with fixed element size
+ *
+ * @param[in] ctx      to allocate the buffer in.
+ * @param[in] size     of buffer to allocate.
+ * @param[in] lock     If true, insert and next operations will lock the buffer.
+ * @return
+ *     - New fring.
+ *     - NULL on error.
+ */
+fr_fring_t *fr_fring_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock)
+{
+       fr_fring_t *fring;
+
+       uint32_t pow;
+
+       /*
+        *      Find the nearest power of 2 (rounding up)
+        */
+       for (pow = 0x00000001;
+            pow < size;
+            pow <<= 1);
+       size = pow;
+       size--;
+
+       fring = talloc_zero(ctx, fr_fring_t);
+       if (!fring) return NULL;
+       talloc_set_destructor(fring, _fring_free);
+
+       fring->data = talloc_zero_array(fring, void *, size);
+       if (!fring->data) {
+               talloc_free(fring);
+               return NULL;
+       }
+       fring->size = size;
+
+       if (lock) {
+               fring->lock = true;
+               pthread_mutex_init(&fring->mutex, NULL);
+       }
+
+       return fring;
+}
+
+/** Insert a new item into the circular buffer, freeing the tail if we hit it
+ *
+ * @param[in] fring    to insert item into
+ * @param[in] in       item to insert (must have been allocated with talloc).
+ * @return
+ *     - 0 if we inserted the item without freeing existing items.
+ *     - 1 if we inserted the item, but needed to free an existing item.
+ */
+int fr_fring_overwrite(fr_fring_t *fring, void *in)
+{
+       bool freed = false;
+       if (fring->lock) pthread_mutex_lock(&fring->mutex);
+
+       if (fring->data[fring->in]) {
+               freed = true;
+               talloc_free(fring->data[fring->in]);
+       }
+
+       fring->data[fring->in] = in;
+       fring->in = (fring->in + 1) & fring->size;
+
+       /* overwrite - out is advanced ahead of in */
+       if (fring->in == fring->out) fring->out = (fring->out + 1) & fring->size;
+
+       if (fring->lock) pthread_mutex_unlock(&fring->mutex);
+
+       return freed ? 1 : 0;
+}
+
+/** Insert a new item into the circular buffer if the buffer is not full
+ *
+ * @param[in] fring    to insert item into.
+ * @param[in] in       item to insert.
+ * @return
+ *     - 0 if we inserted the item.
+ *     - -1 if there's no more space in the buffer to insert items
+ */
+int fr_fring_insert(fr_fring_t *fring, void *in)
+{
+       if (fring->lock) pthread_mutex_lock(&fring->mutex);
+
+       if (fring->data[fring->in]) {
+               if (fring->lock) pthread_mutex_unlock(&fring->mutex);
+
+               return -1;
+       }
+
+       fring->data[fring->in] = in;
+       fring->in = (fring->in + 1) & fring->size;
+
+       /* overwrite - out is advanced ahead of in */
+       if (fring->in == fring->out) fring->out = (fring->out + 1) & fring->size;
+
+       if (fring->lock) pthread_mutex_unlock(&fring->mutex);
+
+       return 0;
+}
+
+/** Remove an item from the buffer
+ *
+ * @param[in] fring    to drain data from.
+ * @return
+ *     - NULL if no dataents in the buffer.
+ *     - An dataent from the buffer reparented to ctx.
+ */
+void *fr_fring_next(fr_fring_t *fring)
+{
+       void *out = NULL;
+
+       if (fring->lock) pthread_mutex_lock(&fring->mutex);
+
+       /* Buffer is empty */
+       if (fring->out == fring->in) goto done;
+
+       out = fring->data[fring->out];
+       fring->data[fring->out] = NULL;
+       fring->out = (fring->out + 1) & fring->size;
+
+done:
+       if (fring->lock) pthread_mutex_unlock(&fring->mutex);
+
+       return out;
+}