diff options
author | Maria Matejka <mq@ucw.cz> | 2021-11-30 18:16:49 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-11-30 21:38:25 +0100 |
commit | 385b3ea3956aefc2868cdd838fc0a90f1d8a7857 (patch) | |
tree | d954b853724153e4a2411d57be5f29e5b9236251 /lib | |
parent | ab0994a10c26bd76b4154a675267d96d19dfb509 (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.c | 2 | ||||
-rw-r--r-- | lib/flowspec_test.c | 8 | ||||
-rw-r--r-- | lib/hash_test.c | 6 | ||||
-rw-r--r-- | lib/io-loop.h | 13 | ||||
-rw-r--r-- | lib/resource.c | 130 | ||||
-rw-r--r-- | lib/resource.h | 15 |
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 */ |