summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-11-30 18:16:49 +0100
committerMaria Matejka <mq@ucw.cz>2021-11-30 21:38:25 +0100
commit385b3ea3956aefc2868cdd838fc0a90f1d8a7857 (patch)
treed954b853724153e4a2411d57be5f29e5b9236251 /lib
parentab0994a10c26bd76b4154a675267d96d19dfb509 (diff)
For safer memory allocations, resources are bound to loops.
Also all loops have their basic resource pool for allocations which are auto-freed when the loop is stopping.
Diffstat (limited to 'lib')
-rw-r--r--lib/event_test.c2
-rw-r--r--lib/flowspec_test.c8
-rw-r--r--lib/hash_test.c6
-rw-r--r--lib/io-loop.h13
-rw-r--r--lib/resource.c130
-rw-r--r--lib/resource.h15
6 files changed, 145 insertions, 29 deletions
diff --git a/lib/event_test.c b/lib/event_test.c
index 9dda3e2a..f8bb303b 100644
--- a/lib/event_test.c
+++ b/lib/event_test.c
@@ -57,8 +57,8 @@ t_ev_run_list(void)
resource_sys_init();
resource_init();
- olock_init();
birdloop_init();
+ olock_init();
io_init();
rt_init();
if_init();
diff --git a/lib/flowspec_test.c b/lib/flowspec_test.c
index f7f70982..518b8fc7 100644
--- a/lib/flowspec_test.c
+++ b/lib/flowspec_test.c
@@ -8,6 +8,7 @@
#include "test/birdtest.h"
#include "lib/flowspec.h"
+#include "lib/io-loop.h"
#define NET_ADDR_FLOW4_(what,prefix,pxlen,data_) \
do \
@@ -446,8 +447,6 @@ t_validation6(void)
static int
t_builder4(void)
{
- resource_init();
-
struct flow_builder *fb = flow_builder_init(&root_pool);
linpool *lp = lp_new_default(&root_pool);
@@ -529,7 +528,6 @@ t_builder6(void)
{
net_addr_ip6 ip;
- resource_init();
linpool *lp = lp_new_default(&root_pool);
struct flow_builder *fb = flow_builder_init(&root_pool);
fb->ipv6 = 1;
@@ -673,6 +671,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
+ resource_init();
+ the_bird_lock();
+ birdloop_init();
bt_test_suite(t_read_length, "Testing get NLRI length");
bt_test_suite(t_write_length, "Testing set NLRI length");
@@ -688,5 +689,6 @@ main(int argc, char *argv[])
bt_test_suite(t_formatting4, "Formatting Flow Specification (IPv4) into text representation");
bt_test_suite(t_formatting6, "Formatting Flow Specification (IPv6) into text representation");
+ the_bird_unlock();
return bt_exit_value();
}
diff --git a/lib/hash_test.c b/lib/hash_test.c
index 59beb7c0..7ef54662 100644
--- a/lib/hash_test.c
+++ b/lib/hash_test.c
@@ -9,7 +9,9 @@
#undef LOCAL_DEBUG
#include "test/birdtest.h"
+#include "test/bt-utils.h"
+#include "lib/io-loop.h"
#include "lib/hash.h"
struct test_node {
@@ -61,8 +63,7 @@ dump_nodes(void)
static void
init_hash_(uint order)
{
- resource_init();
- my_pool = rp_new(&root_pool, "Test pool");
+ my_pool = rp_new(&root_pool, &main_birdloop, "Test pool");
HASH_INIT(hash, my_pool, order);
@@ -290,6 +291,7 @@ int
main(int argc, char *argv[])
{
bt_init(argc, argv);
+ bt_bird_init();
bt_test_suite(t_insert_find, "HASH_INSERT and HASH_FIND");
bt_test_suite(t_insert_find_random, "HASH_INSERT pseudo-random keys and HASH_FIND");
diff --git a/lib/io-loop.h b/lib/io-loop.h
index 25f1b2a3..386a31d5 100644
--- a/lib/io-loop.h
+++ b/lib/io-loop.h
@@ -20,15 +20,15 @@ void sk_reloop(sock *s, struct birdloop *loop);
extern struct birdloop main_birdloop;
-/* Start a new birdloop owned by given pool and domain */
+/* Start a new birdloop owned by given pool and domain.
+ * The loop allocates its internal pool for local allocations
+ * which is freed when the loop itself is stopped. */
struct birdloop *birdloop_new(pool *p, uint order, const char *name);
-/* Stop the loop. At the end, the @stopped callback is called unlocked in tail
- * position to finish cleanup. Run birdloop_free() from that callback to free
- * the loop itself. */
+/* Stop the loop. At the end, the @stopped callback is called with locked
+ * parent to finish cleanup. The loop then frees itself together with its pool. */
void birdloop_stop(struct birdloop *loop, void (*stopped)(void *data), void *data);
void birdloop_stop_self(struct birdloop *loop, void (*stopped)(void *data), void *data);
-void birdloop_free(struct birdloop *loop);
/* Get birdloop's event list */
event_list *birdloop_event_list(struct birdloop *loop);
@@ -36,6 +36,9 @@ event_list *birdloop_event_list(struct birdloop *loop);
/* Get birdloop's time heap */
struct timeloop *birdloop_time_loop(struct birdloop *loop);
+/* Get birdloop's resource pool */
+pool *birdloop_pool(struct birdloop *loop);
+
/* Enter and exit the birdloop */
void birdloop_enter(struct birdloop *loop);
void birdloop_leave(struct birdloop *loop);
diff --git a/lib/resource.c b/lib/resource.c
index 0651406f..c847d41a 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -14,6 +14,7 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "lib/rcu.h"
+#include "lib/io-loop.h"
/**
* DOC: Resource pools
@@ -29,13 +30,6 @@
* is freed upon shutdown of the module.
*/
-struct pool {
- resource r;
- list inside;
- struct pool_pages *pages;
- const char *name;
-};
-
struct pool_pages {
uint free;
uint used;
@@ -68,26 +62,39 @@ static int indent;
/**
* rp_new - create a resource pool
* @p: parent pool
+ * @l: loop to assign
* @name: pool name (to be included in debugging dumps)
*
* rp_new() creates a new resource pool inside the specified
* parent pool.
*/
pool *
-rp_new(pool *p, const char *name)
+rp_new(pool *p, struct birdloop *loop, const char *name)
{
+ ASSERT_DIE(birdloop_inside(p->loop));
+ ASSERT_DIE(birdloop_inside(loop));
+
pool *z = ralloc(p, &pool_class);
+ z->loop = loop;
z->name = name;
init_list(&z->inside);
return z;
}
+_Thread_local static pool *pool_parent = NULL;
+
static void
pool_free(resource *P)
{
+ ASSERT_DIE(pool_parent);
+
pool *p = (pool *) P;
- resource *r, *rr;
+ ASSERT_DIE(birdloop_inside(p->loop));
+
+ pool *parent = pool_parent;
+ pool_parent = p;
+ resource *r, *rr;
r = HEAD(p->inside);
while (rr = (resource *) r->n.next)
{
@@ -105,14 +112,25 @@ pool_free(resource *P)
free_sys_page(p->pages);
}
+
+ pool_parent = parent;
+}
+
+void
+rp_free(pool *p, pool *parent)
+{
+ ASSERT_DIE(pool_parent == NULL);
+ pool_parent = parent;
+ rfree(p);
+ ASSERT_DIE(pool_parent == parent);
+ pool_parent = NULL;
}
static void
-pool_dump(resource *P)
+pool_dump_locked(pool *p)
{
- pool *p = (pool *) P;
resource *r;
-
+
debug("%s\n", p->name);
indent += 3;
WALK_LIST(r, p->inside)
@@ -120,10 +138,47 @@ pool_dump(resource *P)
indent -= 3;
}
-static size_t
-pool_memsize(resource *P)
+static void
+pool_dump(resource *P)
{
pool *p = (pool *) P;
+
+ if (p->loop != pool_parent->loop)
+ birdloop_enter(p->loop);
+
+ pool *parent = pool_parent;
+ pool_parent = p;
+
+ pool_dump_locked(p);
+
+ pool_parent = parent;
+
+ if (p->loop != pool_parent->loop)
+ birdloop_leave(p->loop);
+}
+
+void
+rp_dump(pool *p)
+{
+ int inside = birdloop_inside(p->loop);
+ if (!inside)
+ birdloop_enter(p->loop);
+
+ ASSERT_DIE(pool_parent == NULL);
+ pool_parent = p;
+
+ pool_dump_locked(p);
+
+ ASSERT_DIE(pool_parent == p);
+ pool_parent = NULL;
+
+ if (!inside)
+ birdloop_leave(p->loop);
+}
+
+static size_t
+pool_memsize_locked(pool *p)
+{
resource *r;
size_t sum = sizeof(pool) + ALLOC_OVERHEAD;
@@ -136,6 +191,46 @@ pool_memsize(resource *P)
return sum;
}
+static size_t
+pool_memsize(resource *P)
+{
+ pool *p = (pool *) P;
+
+ pool *parent = pool_parent;
+ pool_parent = p;
+
+ if (p->loop != parent->loop)
+ birdloop_enter(p->loop);
+
+ size_t sum = pool_memsize_locked(p);
+
+ if (p->loop != parent->loop)
+ birdloop_leave(p->loop);
+
+ pool_parent = parent;
+
+ return sum;
+}
+
+size_t
+rp_memsize(pool *p)
+{
+ int inside = birdloop_inside(p->loop);
+ if (!inside)
+ birdloop_enter(p->loop);
+
+ ASSERT_DIE(pool_parent == NULL);
+ pool_parent = p;
+ size_t sum = pool_memsize_locked(p);
+ ASSERT_DIE(pool_parent == p);
+ pool_parent = NULL;
+
+ if (!inside)
+ birdloop_leave(p->loop);
+
+ return sum;
+}
+
static resource *
pool_lookup(resource *P, unsigned long a)
{
@@ -243,12 +338,15 @@ rmemsize(void *res)
void *
ralloc(pool *p, struct resclass *c)
{
+ ASSERT_DIE(p);
+ ASSERT_DIE(birdloop_inside(p->loop));
+
resource *r = xmalloc(c->size);
bzero(r, c->size);
r->class = c;
- if (p)
- add_tail(&p->inside, &r->n);
+ add_tail(&p->inside, &r->n);
+
return r;
}
diff --git a/lib/resource.h b/lib/resource.h
index 26030aea..7adde493 100644
--- a/lib/resource.h
+++ b/lib/resource.h
@@ -34,10 +34,16 @@ struct resclass {
/* Generic resource manipulation */
-typedef struct pool pool;
+typedef struct pool {
+ resource r;
+ list inside;
+ struct pool_pages *pages;
+ struct birdloop *loop;
+ const char *name;
+} pool;
void resource_init(void);
-pool *rp_new(pool *, const char *); /* Create new pool */
+
void rfree(void *); /* Free single resource */
void rdump(void *); /* Dump to debug output */
size_t rmemsize(void *res); /* Return size of memory used by the resource */
@@ -46,6 +52,11 @@ void rmove(void *, pool *); /* Move to a different pool */
void *ralloc(pool *, struct resclass *);
+pool *rp_new(pool *, struct birdloop *loop, const char *); /* Create new pool */
+void rp_free(pool *p, pool *parent); /* Free parent pool */
+size_t rp_memsize(pool *p); /* Return size of memory used by the pool */
+void rp_dump(pool *p); /* Dump pool to debug output */
+
extern pool root_pool;
/* Normal memory blocks */