]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add init parameter to LST creation closes #4210
authorJames Jones <jejones3141@gmail.com>
Thu, 26 Aug 2021 16:02:56 +0000 (11:02 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 26 Aug 2021 18:36:38 +0000 (13:36 -0500)
The parameter determines the initial capacity choice: 0 will get
the default initial capacity, while any other value will be rounded
up to a power of 2 and used as the initial capacity.

src/lib/util/event.c
src/lib/util/lst.c
src/lib/util/lst.h
src/lib/util/lst_tests.c

index 7c7a31f307a73958da19653f627188af0b87af9a..3c86488535f3818f53b8e7f09790c0f8d54a2332 100644 (file)
@@ -2277,7 +2277,7 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t statu
        el->kq = -1;    /* So destructor can be used before kqueue() provides us with fd */
        talloc_set_destructor(el, _event_list_free);
 
-       el->times = fr_lst_talloc_alloc(el, fr_event_timer_cmp, fr_event_timer_t, lst_id);
+       el->times = fr_lst_talloc_alloc(el, fr_event_timer_cmp, fr_event_timer_t, lst_id, 0);
        if (!el->times) {
                fr_strerror_const("Failed allocating event lst");
        error:
@@ -2292,7 +2292,7 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t statu
        }
 
 #ifdef LOCAL_PID
-       el->pids = fr_lst_talloc_alloc(el, fr_event_pid_cmp, fr_event_pid_t, lst_id);
+       el->pids = fr_lst_talloc_alloc(el, fr_event_pid_cmp, fr_event_pid_t, lst_id, 0);
        if (!el->pids) {
                fr_strerror_const("Failed allocating PID lst");
                goto error;
index 36b5ee50a5f7de541a723de0f011d76a2d3c9d27..e36190fe2ab80ea612c349315e7a70cea2ce4132 100644 (file)
@@ -23,6 +23,7 @@
 RCSID("$Id$")
 
 #include <freeradius-devel/util/lst.h>
+#include <freeradius-devel/util/misc.h>
 #include <freeradius-devel/util/rand.h>
 #include <freeradius-devel/util/strerror.h>
 
@@ -47,6 +48,8 @@ RCSID("$Id$")
 #define INITIAL_CAPACITY       2048
 #define INITIAL_STACK_CAPACITY 32
 
+#define is_power_of_2(_n)      ((_n) && (((_n) & ((_n) - 1)) == 0))
+
 typedef unsigned int stack_index_t;
 
 typedef struct {
@@ -147,8 +150,7 @@ static inline CC_HINT(always_inline, nonnull) void *pivot_item(fr_lst_t *lst, st
  * The index is visible for the size and length functions, since they need
  * to know the subtree they're working on.
  */
-static inline CC_HINT(always_inline, nonnull)
-bool is_bucket(fr_lst_t *lst, stack_index_t idx)
+static inline CC_HINT(always_inline, nonnull) bool is_bucket(fr_lst_t *lst, stack_index_t idx)
 {
        return lst_length(lst, idx) == 1;
 }
@@ -218,11 +220,17 @@ void stack_set(pivot_stack_t *s, stack_index_t idx, fr_lst_index_t new_value)
        s->data[idx] = new_value;
 }
 
-fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset)
+fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset, fr_lst_index_t init)
 {
        fr_lst_t        *lst;
        pivot_stack_t   *s;
 
+       if (!init) {
+               init = INITIAL_CAPACITY;
+       } else if (!is_power_of_2(init)) {
+               init = 1 << fr_high_bit_pos(init);
+       }
+
        /*
         *      Pre-allocate stack memory as it is
         *      unlikely to need to grow in practice.
@@ -238,7 +246,7 @@ fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, siz
        lst = talloc_zero_pooled_object(ctx, fr_lst_t, 3, (INITIAL_STACK_CAPACITY * sizeof(fr_lst_index_t)));
        if (unlikely(!lst)) return NULL;
 
-       lst->capacity = INITIAL_CAPACITY;
+       lst->capacity = init;
        lst->p = talloc_array(lst, void *, lst->capacity);
        if (unlikely(!lst->p)) {
        cleanup:
index 053aa7b872c17eb58a838f0986fcb62feb5d57a1..465bf838c79d101db888d718e3b7a613dab2cd3c 100644 (file)
@@ -56,9 +56,14 @@ typedef int8_t (*fr_lst_cmp_t)(void const *a, void const *b);
  * @param[in] _cmp             Comparator used to compare elements.
  * @param[in] _type            Of elements.
  * @param[in] _field           to store LST indexes in.
+ * @param[in] _init            initial capacity (0 for default initial size);
+ *                             the capacity will be rounded up to a power of two.
+ * @return
+ *     - A pointer to the new LST.
+ *     - NULL on error
  */
-#define fr_lst_alloc(_ctx, _cmp, _type, _field) \
-       _fr_lst_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field))
+#define fr_lst_alloc(_ctx, _cmp, _type, _field, _init) \
+       _fr_lst_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field), _init)
 
 /** Creates an LST that verifies elements are of a specific talloc type
  *
@@ -66,14 +71,16 @@ typedef int8_t (*fr_lst_cmp_t)(void const *a, void const *b);
  * @param[in] _cmp             Comparator used to compare elements.
  * @param[in] _talloc_type     of elements.
  * @param[in] _field           to store heap indexes in.
+ * @param[in] _init            initial capacity (0 for default initial size);
+ *                             the capacity will be rounded up to a power of two.
  * @return
  *     - A pointer to the new LST.
  *     - NULL on error.
  */
-#define fr_lst_talloc_alloc(_ctx, _cmp, _talloc_type, _field) \
-       _fr_lst_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field))
+#define fr_lst_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init) \
+       _fr_lst_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field), _init)
 
-fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset) CC_HINT(nonnull(2));
+fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset, fr_lst_index_t init) CC_HINT(nonnull(2));
 
 /** Check if an entry is inserted into an LST.
  *
index 4b660c32b471207e50a984deeb465500162cf8c8..d49577432d25ac66e72fdcdbc7267b96a767c14e 100644 (file)
@@ -67,7 +67,7 @@ static void lst_test_basic(void)
        fr_lst_t        *lst;
        lst_thing       values[NVALUES];
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, NVALUES);
        TEST_CHECK(lst != NULL);
 
        populate_values(values, NUM_ELEMENTS(values));
@@ -83,6 +83,7 @@ static void lst_test_basic(void)
                TEST_CHECK(value != NULL);
                TEST_CHECK(!fr_lst_entry_inserted(value->idx));
                TEST_CHECK(value->data == i);
+               TEST_MSG("iteration %u, popped %u", i, value->data);
        }
        talloc_free(lst);
 }
@@ -104,7 +105,7 @@ static void lst_test(int skip)
                done_init = true;
        }
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
        TEST_CHECK(lst != NULL);
 
        values = calloc(LST_TEST_SIZE, sizeof(lst_thing));
@@ -182,7 +183,7 @@ static void lst_stress_realloc(void)
                done_init = true;
        }
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
        TEST_CHECK(lst != NULL);
        hp = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, 0);
 
@@ -259,7 +260,7 @@ static void lst_burn_in(void)
        array = calloc(BURN_IN_OPS, sizeof(lst_thing));
        for (unsigned int i = 0; i < BURN_IN_OPS; i++) array[i].data = rand() % 65537;
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
 
        for (unsigned int i = 0; i < BURN_IN_OPS; i++) {
                lst_thing       *ret_thing = NULL;
@@ -311,7 +312,7 @@ static void lst_cycle(void)
                done_init = true;
        }
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
        TEST_CHECK(lst != NULL);
 
        values = calloc(LST_CYCLE_SIZE, sizeof(lst_thing));
@@ -388,7 +389,7 @@ static void lst_iter(void)
        lst_thing       values[NVALUES], *data;
 
 
-       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+       lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
        TEST_CHECK(lst != NULL);
 
        populate_values(values, NUM_ELEMENTS(values));
@@ -449,7 +450,7 @@ static void queue_cmp(unsigned int count)
                populate_values(values, count);
 
                start_alloc = fr_time();
-               lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+               lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
                end_alloc = fr_time();
                TEST_CHECK(lst != NULL);