summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/conf.c4
-rw-r--r--filter/tree_test.c2
-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
-rw-r--r--nest/a-path_test.c12
-rw-r--r--nest/a-set_test.c13
-rw-r--r--nest/cli.c8
-rw-r--r--nest/cmds.c8
-rw-r--r--nest/config.Y2
-rw-r--r--nest/iface.c2
-rw-r--r--nest/proto.c41
-rw-r--r--nest/route.h4
-rw-r--r--nest/rt-attr.c4
-rw-r--r--nest/rt-table.c69
-rw-r--r--proto/babel/babel.c2
-rw-r--r--proto/bfd/bfd.c8
-rw-r--r--proto/bfd/bfd.h2
-rw-r--r--proto/mrt/mrt.c5
-rw-r--r--proto/mrt/mrt.h1
-rw-r--r--proto/ospf/iface.c6
-rw-r--r--proto/ospf/neighbor.c4
-rw-r--r--proto/radv/radv.c4
-rw-r--r--proto/rpki/rpki.c2
-rw-r--r--sysdep/unix/io-loop.c72
-rw-r--r--sysdep/unix/io-loop.h3
-rw-r--r--sysdep/unix/krt.c2
-rw-r--r--sysdep/unix/main.c2
-rw-r--r--test/bt-utils.c2
32 files changed, 301 insertions, 157 deletions
diff --git a/conf/conf.c b/conf/conf.c
index 58abcde1..c6837a07 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -89,7 +89,7 @@ int undo_available; /* Undo was not requested from last reconfiguration */
struct config *
config_alloc(const char *name)
{
- pool *p = rp_new(&root_pool, "Config");
+ pool *p = rp_new(&root_pool, &main_birdloop, "Config");
linpool *l = lp_new_default(p);
struct config *c = lp_allocz(l, sizeof(struct config));
@@ -196,7 +196,7 @@ void
config_free(struct config *c)
{
if (c)
- rfree(c->pool);
+ rp_free(c->pool, &root_pool);
}
void
diff --git a/filter/tree_test.c b/filter/tree_test.c
index 6472d17e..883d13bf 100644
--- a/filter/tree_test.c
+++ b/filter/tree_test.c
@@ -20,7 +20,7 @@ start_conf_env(void)
{
bt_bird_init();
- pool *p = rp_new(&root_pool, "helper_pool");
+ pool *p = rp_new(&root_pool, &main_birdloop, "helper_pool");
linpool *l = lp_new_default(p);
cfg_mem = l;
}
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 */
diff --git a/nest/a-path_test.c b/nest/a-path_test.c
index 2e6e4956..2e6683f2 100644
--- a/nest/a-path_test.c
+++ b/nest/a-path_test.c
@@ -12,6 +12,7 @@
#include "nest/route.h"
#include "nest/attrs.h"
#include "lib/resource.h"
+#include "lib/io-loop.h"
#define TESTS_NUM 30
#define AS_PATH_LENGTH 1000
@@ -23,8 +24,6 @@
static int
t_as_path_match(void)
{
- resource_init();
-
int round;
for (round = 0; round < TESTS_NUM; round++)
{
@@ -70,8 +69,6 @@ t_as_path_match(void)
static int
t_path_format(void)
{
- resource_init();
-
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@@ -116,8 +113,6 @@ count_asn_in_array(const u32 *array, u32 asn)
static int
t_path_include(void)
{
- resource_init();
-
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@@ -161,8 +156,6 @@ t_path_include(void)
static int
t_as_path_converting(void)
{
- resource_init();
-
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@@ -211,6 +204,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
+ resource_init();
+ the_bird_lock();
+ birdloop_init();
bt_test_suite(t_as_path_match, "Testing AS path matching and some a-path utilities.");
bt_test_suite(t_path_format, "Testing formating as path into byte buffer");
diff --git a/nest/a-set_test.c b/nest/a-set_test.c
index efd1b67d..f8f6e781 100644
--- a/nest/a-set_test.c
+++ b/nest/a-set_test.c
@@ -13,6 +13,7 @@
#include "nest/route.h"
#include "nest/attrs.h"
#include "lib/resource.h"
+#include "lib/io-loop.h"
#define SET_SIZE 10
static const struct adata *set_sequence; /* <0; SET_SIZE) */
@@ -71,7 +72,6 @@ t_set_int_contains(void)
{
int i;
- resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
bt_assert(int_set_get_size(set_sequence) == SET_SIZE);
@@ -92,7 +92,6 @@ t_set_int_contains(void)
static int
t_set_int_union(void)
{
- resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
const struct adata *set_union;
@@ -111,7 +110,6 @@ t_set_int_union(void)
static int
t_set_int_format(void)
{
- resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE_FOR_FORMAT_OUTPUT);
bt_assert(int_set_format(set_sequence, 0, 0, buf, BUFFER_SIZE) == 0);
@@ -132,7 +130,6 @@ t_set_int_format(void)
static int
t_set_int_delete(void)
{
- resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
const struct adata *deleting_sequence = set_sequence;
@@ -160,7 +157,6 @@ t_set_ec_contains(void)
{
u32 i;
- resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
bt_assert(ec_set_get_size(set_sequence) == SET_SIZE);
@@ -181,7 +177,6 @@ t_set_ec_contains(void)
static int
t_set_ec_union(void)
{
- resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
const struct adata *set_union;
@@ -200,8 +195,6 @@ t_set_ec_union(void)
static int
t_set_ec_format(void)
{
- resource_init();
-
const struct adata empty_as_path = {};
set_sequence = set_sequence_same = set_sequence_higher = set_random = &empty_as_path;
lp = lp_new_default(&root_pool);
@@ -222,7 +215,6 @@ t_set_ec_format(void)
static int
t_set_ec_delete(void)
{
- resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
const struct adata *deleting_sequence = set_sequence;
@@ -248,6 +240,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
+ resource_init();
+ the_bird_lock();
+ birdloop_init();
bt_test_suite(t_set_int_contains, "Testing sets of integers: contains, get_data");
bt_test_suite(t_set_int_format, "Testing sets of integers: format");
diff --git a/nest/cli.c b/nest/cli.c
index b54a0d76..7e5d2151 100644
--- a/nest/cli.c
+++ b/nest/cli.c
@@ -262,7 +262,7 @@ cli_command(struct cli *c)
log(L_TRACE "CLI: %s", c->rx_buf);
bzero(&f, sizeof(f));
f.mem = c->parser_pool;
- f.pool = rp_new(c->pool, "Config");
+ f.pool = rp_new(c->pool, &main_birdloop, "Config");
init_list(&f.symbols);
cf_read_hook = cli_cmd_read_hook;
cli_rh_pos = c->rx_buf;
@@ -308,7 +308,7 @@ cli_event(void *data)
cli *
cli_new(void *priv)
{
- pool *p = rp_new(cli_pool, "CLI");
+ pool *p = rp_new(cli_pool, &main_birdloop, "CLI");
cli *c = mb_alloc(p, sizeof(cli));
bzero(c, sizeof(cli));
@@ -413,7 +413,7 @@ cli_free(cli *c)
c->cleanup(c);
if (c == cmd_reconfig_stored_cli)
cmd_reconfig_stored_cli = NULL;
- rfree(c->pool);
+ rp_free(c->pool, &root_pool);
}
/**
@@ -425,7 +425,7 @@ cli_free(cli *c)
void
cli_init(void)
{
- cli_pool = rp_new(&root_pool, "CLI");
+ cli_pool = rp_new(&root_pool, &main_birdloop, "CLI");
init_list(&cli_log_hooks);
cli_log_inited = 1;
}
diff --git a/nest/cmds.c b/nest/cmds.c
index 18f39eb5..2f2ad94c 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -88,10 +88,10 @@ void
cmd_show_memory(void)
{
cli_msg(-1018, "BIRD memory usage");
- print_size("Routing tables:", rmemsize(rt_table_pool));
- print_size("Route attributes:", rmemsize(rta_pool));
- print_size("Protocols:", rmemsize(proto_pool));
- print_size("Total:", rmemsize(&root_pool));
+ print_size("Routing tables:", rp_memsize(rt_table_pool));
+ print_size("Route attributes:", rp_memsize(rta_pool));
+ print_size("Protocols:", rp_memsize(proto_pool));
+ print_size("Total:", rp_memsize(&root_pool));
cli_msg(0, "");
}
diff --git a/nest/config.Y b/nest/config.Y
index 0914048b..f9ed0e69 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -810,7 +810,7 @@ sym_args:
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
-{ rdump(&root_pool); cli_msg(0, ""); } ;
+{ rp_dump(&root_pool); cli_msg(0, ""); } ;
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
{ sk_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
diff --git a/nest/iface.c b/nest/iface.c
index 5cb9e814..dd4af243 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -713,7 +713,7 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
void
if_init(void)
{
- if_pool = rp_new(&root_pool, "Interfaces");
+ if_pool = rp_new(&root_pool, &main_birdloop, "Interfaces");
init_list(&iface_list);
strcpy(default_vrf.name, "default");
neigh_init(if_pool);
diff --git a/nest/proto.c b/nest/proto.c
index 2d30e640..a18d9332 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -666,7 +666,10 @@ static uint channel_aux_imex(struct channel_aux_table *cat)
static void
channel_aux_stopped(void *data)
{
- struct channel_aux_table *cat = data;
+ struct channel_aux_table *cat;
+ RT_LOCKED((rtable *) data, t)
+ cat = t->config->owner;
+
struct channel *c = cat->c;
if (channel_aux_imex(cat))
@@ -674,7 +677,6 @@ channel_aux_stopped(void *data)
else
c->in_table = NULL;
- rfree(cat->tab->priv.rp);
mb_free(cat);
channel_check_stopped(c);
}
@@ -694,7 +696,7 @@ channel_aux_export_stopped(struct rt_export_request *req)
int del;
RT_LOCKED(cat->tab, t)
- del = !!t->delete_event;
+ del = !!t->delete;
if (del)
return;
@@ -708,10 +710,7 @@ static void
channel_aux_stop(struct channel_aux_table *cat)
{
RT_LOCKED(cat->tab, t)
- {
- t->delete_event = ev_new_init(t->rp, channel_aux_stopped, cat);
- t->delete_event->list = proto_event_list(cat->c->proto);
- }
+ t->delete = channel_aux_stopped;
cat->push_stopped = (event) {
.hook = channel_aux_import_stopped,
@@ -889,6 +888,7 @@ channel_setup_in_table(struct channel *c, int best)
bsprintf(cat->name, "%s.%s.import", c->proto->name, c->name);
+ cat->tab_cf.owner = cat;
cat->tab_cf.name = cat->name;
cat->tab_cf.addr_type = c->net_type;
cat->tab_cf.cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
@@ -933,6 +933,7 @@ channel_setup_out_table(struct channel *c)
bsprintf(cat->name, "%s.%s.export", c->proto->name, c->name);
+ cat->tab_cf.owner = cat;
cat->tab_cf.name = cat->name;
cat->tab_cf.addr_type = c->net_type;
cat->tab_cf.cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
@@ -1387,9 +1388,6 @@ proto_configure_channel(struct proto *p, struct channel **pc, struct channel_con
static void
proto_cleanup(struct proto *p)
{
- rfree(p->pool);
- p->pool = NULL;
-
p->active = 0;
proto_log_state_change(p);
proto_rethink_goal(p);
@@ -1400,13 +1398,13 @@ proto_loop_stopped(void *ptr)
{
struct proto *p = ptr;
- birdloop_enter(&main_birdloop);
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
p->loop = &main_birdloop;
+ p->pool = NULL;
p->event->list = NULL;
- proto_cleanup(p);
- birdloop_leave(&main_birdloop);
+ proto_cleanup(p);
}
static void
@@ -1426,7 +1424,11 @@ proto_event(void *ptr)
if (p->loop != &main_birdloop)
birdloop_stop_self(p->loop, proto_loop_stopped, p);
else
+ {
+ rp_free(p->pool, proto_pool);
+ p->pool = NULL;
proto_cleanup(p);
+ }
}
@@ -1490,13 +1492,16 @@ proto_start(struct proto *p)
void *nb = mb_alloc(proto_pool, ns);
ASSERT_DIE(ns - 1 == bsnprintf(nb, ns, "Protocol %s", p->cf->name));
- p->pool = rp_new(proto_pool, nb);
-
if (graceful_restart_state == GRS_INIT)
p->gr_recovery = 1;
- if (p->cf->loop_order != DOMAIN_ORDER(the_bird))
- p->loop = birdloop_new(p->pool, p->cf->loop_order, nb);
+ if (p->cf->loop_order == DOMAIN_ORDER(the_bird))
+ p->pool = rp_new(proto_pool, &main_birdloop, nb);
+ else
+ {
+ p->loop = birdloop_new(proto_pool, p->cf->loop_order, nb);
+ p->pool = birdloop_pool(p->loop);
+ }
p->event->list = proto_event_list(p);
@@ -2177,7 +2182,7 @@ protos_build(void)
proto_build(&proto_perf);
#endif
- proto_pool = rp_new(&root_pool, "Protocols");
+ proto_pool = rp_new(&root_pool, &main_birdloop, "Protocols");
proto_shutdown_timer = tm_new(proto_pool);
proto_shutdown_timer->hook = proto_shutdown_loop;
}
diff --git a/nest/route.h b/nest/route.h
index b5d44040..f060ad63 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -174,7 +174,7 @@ typedef struct rtable_private {
struct event *announce_event; /* Event to announce pending exports */
struct event *ec_event; /* Event to prune finished exports */
struct event *hcu_event; /* Event to update host cache */
- struct event *delete_event; /* Event to delete the table */
+ void (*delete)(void *); /* Delete callback (in parent loop context) */
btime last_rt_change; /* Last time when route changed */
btime base_settle_time; /* Start time of rtable settling interval */
btime gc_time; /* Time of last GC */
@@ -212,7 +212,7 @@ typedef union {
struct rtable_config {
node n;
char *name;
- struct config *config;
+ void *owner; /* Main config if global table, channel_aux_table if channel table */
rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
uint addr_type; /* Type of address data stored in table (NET_*) */
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 9a5498ed..357cd216 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -117,7 +117,7 @@ static void
rte_src_init(void)
{
src_domain = DOMAIN_NEW(attrs, "Route sources");
- src_pool = rp_new(&root_pool, "Route sources");
+ src_pool = rp_new(&root_pool, &main_birdloop, "Route sources");
rte_src_slab = sl_new(src_pool, sizeof(struct rte_src));
idm_init(&src_ids, src_pool, SRC_ID_INIT_SIZE);
@@ -1534,7 +1534,7 @@ rta_init(void)
{
attrs_domain = DOMAIN_NEW(attrs, "Attributes");
- rta_pool = rp_new(&root_pool, "Attributes");
+ rta_pool = rp_new(&root_pool, &main_birdloop, "Attributes");
rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 8566fbf8..cd0d6291 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1695,7 +1695,7 @@ rt_export_stopped(void *data)
RT_LOCKED(hook->table, tab)
{
/* Free the hook together with its coroutine. */
- rfree(hook->pool);
+ rp_free(hook->pool, tab->rp);
rt_unlock_table(tab);
DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
@@ -1777,7 +1777,7 @@ rt_request_export(rtable *t, struct rt_export_request *req)
rtable_private *tab = RT_PRIV(t);
rt_lock_table(tab);
- pool *p = rp_new(tab->rp, "Export hook");
+ pool *p = rp_new(tab->rp, tab->loop, "Export hook");
struct rt_export_hook *hook = req->hook = mb_allocz(p, sizeof(struct rt_export_hook));
hook->pool = p;
@@ -1935,7 +1935,7 @@ rt_dump(rtable *tab)
{
RT_LOCK(tab);
rtable_private *t = RT_PRIV(tab);
- debug("Dump of routing table <%s>%s\n", t->name, t->delete_event ? " (deleted)" : "");
+ debug("Dump of routing table <%s>%s\n", t->name, t->delete ? " (deleted)" : "");
#ifdef DEBUGGING
fib_check(&t->fib);
#endif
@@ -1969,7 +1969,7 @@ rt_dump_hooks(rtable *t)
{
RT_LOCK(t);
rtable_private *tab = RT_PRIV(t);
- debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->delete_event ? " (deleted)" : "");
+ debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->delete ? " (deleted)" : "");
debug(" nhu_state=%u hcu_scheduled=%u use_count=%d rt_count=%u\n",
atomic_load(&tab->nhu_state), ev_active(tab->hcu_event), tab->use_count, tab->rt_count);
debug(" last_rt_change=%t gc_time=%t gc_counter=%d prune_state=%u\n",
@@ -2142,6 +2142,9 @@ rt_free(resource *_r)
ASSERT_DIE(EMPTY_LIST(r->imports));
ASSERT_DIE(EMPTY_LIST(r->exports));
+ if (r->hostcache)
+ rt_free_hostcache(r);
+
/* Freed automagically by the resource pool
fib_free(&r->fib);
hmap_free(&r->id_map);
@@ -2175,10 +2178,14 @@ rt_setup(pool *pp, struct rtable_config *cf)
void *nb = mb_alloc(pp, ns);
ASSERT_DIE(ns - 1 == bsnprintf(nb, ns, "Routing table %s", cf->name));
- pool *p = rp_new(pp, nb);
+ struct birdloop *l = birdloop_new(pp, DOMAIN_ORDER(rtable), nb);
+ pool *p = birdloop_pool(l);
+
+ birdloop_enter(l);
rtable_private *t = ralloc(p, &rt_class);
t->rp = p;
+ t->loop = l;
t->rte_slab = sl_new(p, sizeof(struct rte_storage));
@@ -2197,8 +2204,6 @@ rt_setup(pool *pp, struct rtable_config *cf)
init_list(&t->pending_exports);
init_list(&t->subscribers);
- t->loop = birdloop_new(p, DOMAIN_ORDER(rtable), nb);
-
t->announce_event = ev_new_init(p, rt_announce_exports, t);
t->ec_event = ev_new_init(p, rt_export_cleanup, t);
t->prune_event = ev_new_init(p, rt_prune_table, t);
@@ -2216,6 +2221,8 @@ rt_setup(pool *pp, struct rtable_config *cf)
t->nhu_lp = lp_new_default(p);
mb_move(nb, p);
+ birdloop_leave(l);
+
return (rtable *) t;
}
@@ -2229,7 +2236,7 @@ void
rt_init(void)
{
rta_init();
- rt_table_pool = rp_new(&root_pool, "Routing tables");
+ rt_table_pool = rp_new(&root_pool, &main_birdloop, "Routing tables");
init_list(&routing_tables);
ev_init_cork(&rt_cork, "Route Table Cork");
}
@@ -2819,7 +2826,7 @@ rt_new_table(struct symbol *s, uint addr_type)
c->min_rr_settle_time = 30 S;
c->max_rr_settle_time = 90 S;
c->cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
- c->config = new_config;
+ c->owner = new_config;
add_tail(&new_config->tables, &c->n);
@@ -2844,18 +2851,6 @@ rt_lock_table(rtable_private *r)
r->use_count++;
}
-static void
-rt_loop_stopped(void *data)
-{
- rtable_private *r = data;
- birdloop_free(r->loop);
- r->loop = NULL;
- r->prune_event->list = r->ec_event->list = NULL;
- r->nhu_event->list = r->hcu_event->list = NULL;
- r->announce_event->list = NULL;
- ev_send(r->delete_event->list, r->delete_event);
-}
-
/**
* rt_unlock_table - unlock a routing table
* @r: routing table to be unlocked
@@ -2867,10 +2862,9 @@ rt_loop_stopped(void *data)
void
rt_unlock_table(rtable_private *r)
{
- if (!--r->use_count && r->delete_event &&
+ if (!--r->use_count && r->delete &&
!r->prune_state && !atomic_load_explicit(&r->nhu_state, memory_order_acquire))
- /* Delete the routing table by freeing its pool */
- birdloop_stop_self(r->loop, rt_loop_stopped, r);
+ birdloop_stop_self(r->loop, r->delete, r);
}
static struct rtable_config *
@@ -2883,22 +2877,16 @@ rt_find_table_config(struct config *cf, char *name)
static void
rt_done(void *data)
{
- rtable_private *t = data;
- ASSERT_DIE(t->loop == NULL);
-
- struct rtable_config *tc = t->config;
- struct config *c = tc->config;
-
- tc->table = NULL;
- rem_node(&t->n);
-
- if (t->hostcache)
- rt_free_hostcache(t);
+ RT_LOCKED((rtable *) data, t)
+ {
+ struct rtable_config *tc = t->config;
+ struct config *c = tc->owner;
- rfree(t->delete_event);
- rfree(t->rp);
+ tc->table = NULL;
+ rem_node(&t->n);
- config_del_obstacle(c);
+ config_del_obstacle(c);
+ }
}
/**
@@ -2925,7 +2913,7 @@ rt_commit(struct config *new, struct config *old)
{
RT_LOCK(o->table);
rtable_private *ot = RT_PRIV(o->table);
- if (!ot->delete_event)
+ if (!ot->delete)
{
r = rt_find_table_config(new, o->name);
if (r && (r->addr_type == o->addr_type) && !new->shutdown)
@@ -2941,8 +2929,7 @@ rt_commit(struct config *new, struct config *old)
{
DBG("\t%s: deleted\n", o->name);
rt_lock_table(ot);
- ot->delete_event = ev_new_init(&root_pool, rt_done, ot);
- ot->delete_event->list = &global_event_list;
+ ot->delete = rt_done;
config_add_obstacle(old);
rt_unlock_table(ot);
}
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 40e85a16..515b27e5 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1747,7 +1747,7 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con
TRACE(D_EVENTS, "Adding interface %s", new->name);
- pool *pool = rp_new(p->p.pool, new->name);
+ pool *pool = rp_new(p->p.pool, p->p.loop, new->name);
ifa = mb_allocz(pool, sizeof(struct babel_iface));
ifa->proto = p;
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index dd3488d4..c9b12aa1 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -452,8 +452,8 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
s->passive = s->cf.passive;
s->tx_csn = random_u32();
- s->tx_timer = tm_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0);
- s->hold_timer = tm_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0);
+ s->tx_timer = tm_new_init(p->p.pool, bfd_tx_timer_hook, s, 0, 0);
+ s->hold_timer = tm_new_init(p->p.pool, bfd_hold_timer_hook, s, 0, 0);
bfd_session_update_tx_interval(s);
bfd_session_control_tx_timer(s, 1);
@@ -581,7 +581,7 @@ bfd_get_iface(struct bfd_proto *p, ip_addr local, struct iface *iface)
struct bfd_config *cf = (struct bfd_config *) (p->p.cf);
struct bfd_iface_config *ic = bfd_find_iface_config(cf, iface);
- ifa = mb_allocz(p->tpool, sizeof(struct bfd_iface));
+ ifa = mb_allocz(p->p.pool, sizeof(struct bfd_iface));
ifa->local = local;
ifa->iface = iface;
ifa->cf = ic;
@@ -1062,8 +1062,6 @@ bfd_start(struct proto *P)
pthread_spin_init(&p->lock, PTHREAD_PROCESS_PRIVATE);
- p->tpool = rp_new(P->pool, "BFD loop pool");
-
p->session_slab = sl_new(P->pool, sizeof(struct bfd_session));
HASH_INIT(p->session_hash_id, P->pool, 8);
HASH_INIT(p->session_hash_ip, P->pool, 8);
diff --git a/proto/bfd/bfd.h b/proto/bfd/bfd.h
index 8430064b..475b3a11 100644
--- a/proto/bfd/bfd.h
+++ b/proto/bfd/bfd.h
@@ -90,8 +90,6 @@ struct bfd_proto
pthread_spinlock_t lock;
- pool *tpool;
-
node bfd_node;
slab *session_slab;
diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c
index b40592d2..e12f7743 100644
--- a/proto/mrt/mrt.c
+++ b/proto/mrt/mrt.c
@@ -561,10 +561,11 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
static struct mrt_table_dump_state *
mrt_table_dump_init(pool *pp)
{
- pool *pool = rp_new(pp, "MRT Table Dump");
+ pool *pool = rp_new(pp, &main_birdloop, "MRT Table Dump");
struct mrt_table_dump_state *s = mb_allocz(pool, sizeof(struct mrt_table_dump_state));
s->pool = pool;
+ s->parent = pp;
s->linpool = lp_new(pool, 4080);
s->peer_lp = lp_new(pool, 4080);
mrt_buffer_init(&s->buf, pool, 2 * MRT_ATTR_BUFFER_SIZE);
@@ -601,7 +602,7 @@ mrt_table_dump_free(struct mrt_table_dump_state *s)
config_del_obstacle(s->config);
- rfree(s->pool);
+ rp_free(s->pool, s->parent);
}
diff --git a/proto/mrt/mrt.h b/proto/mrt/mrt.h
index 04865089..2e616f6f 100644
--- a/proto/mrt/mrt.h
+++ b/proto/mrt/mrt.h
@@ -67,6 +67,7 @@ struct mrt_table_dump_state {
/* Allocated by mrt_table_dump_init() */
pool *pool; /* Pool for table dump */
+ pool *parent; /* Parent pool for cleanup */
linpool *linpool; /* Temporary linear pool */
linpool *peer_lp; /* Linear pool for peer entries in peer_hash */
buffer buf; /* Buffer for MRT messages */
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 4cd45033..2aae341a 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -311,7 +311,7 @@ ospf_iface_remove(struct ospf_iface *ifa)
ospf_iface_sm(ifa, ISM_DOWN);
rem_node(NODE ifa);
- rfree(ifa->pool);
+ rp_free(ifa->pool, p->p.pool);
}
void
@@ -567,7 +567,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
OSPF_TRACE(D_EVENTS, "Adding interface %s (%N) to area %R",
iface->name, &addr->prefix, oa->areaid);
- pool = rp_new(p->p.pool, "OSPF Interface");
+ pool = rp_new(p->p.pool, p->p.loop, "OSPF Interface");
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
ifa->iface = iface;
ifa->addr = addr;
@@ -687,7 +687,7 @@ ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
/* Vlink ifname is stored just after the ospf_iface structure */
- pool = rp_new(p->p.pool, "OSPF Vlink");
+ pool = rp_new(p->p.pool, p->p.loop, "OSPF Vlink");
ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
ifa->oa = p->backbone;
ifa->cf = ip;
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index ca369819..48e38556 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -80,7 +80,7 @@ struct ospf_neighbor *
ospf_neighbor_new(struct ospf_iface *ifa)
{
struct ospf_proto *p = ifa->oa->po;
- struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
+ struct pool *pool = rp_new(p->p.pool, p->p.loop, "OSPF Neighbor");
struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
n->pool = pool;
@@ -120,7 +120,7 @@ ospf_neigh_down(struct ospf_neighbor *n)
s_get(&(n->dbsi));
release_lsrtl(p, n);
rem_node(NODE n);
- rfree(n->pool);
+ rp_free(n->pool, p->p.pool);
OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
}
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index d572c1b7..b0f15514 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -284,7 +284,7 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf
RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name);
- pool *pool = rp_new(p->p.pool, iface->name);
+ pool *pool = rp_new(p->p.pool, p->p.loop, iface->name);
ifa = mb_allocz(pool, sizeof(struct radv_iface));
ifa->pool = pool;
ifa->ra = p;
@@ -317,7 +317,7 @@ radv_iface_remove(struct radv_iface *ifa)
rem_node(NODE ifa);
- rfree(ifa->pool);
+ rp_free(ifa->pool, p->p.pool);
}
static void
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index cc86ab6a..afba2216 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -596,7 +596,7 @@ rpki_check_expire_interval(uint seconds)
static struct rpki_cache *
rpki_init_cache(struct rpki_proto *p, struct rpki_config *cf)
{
- pool *pool = rp_new(p->p.pool, cf->hostname);
+ pool *pool = rp_new(p->p.pool, p->p.loop, cf->hostname);
struct rpki_cache *cache = mb_allocz(pool, sizeof(struct rpki_cache));
diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c
index c7cf4ad2..769f01ba 100644
--- a/sysdep/unix/io-loop.c
+++ b/sysdep/unix/io-loop.c
@@ -48,6 +48,12 @@ birdloop_time_loop(struct birdloop *loop)
return &loop->time;
}
+pool *
+birdloop_pool(struct birdloop *loop)
+{
+ return loop->pool;
+}
+
_Bool
birdloop_inside(struct birdloop *loop)
{
@@ -333,31 +339,59 @@ birdloop_init(void)
times_update();
timers_init(&main_birdloop.time, &root_pool);
+ root_pool.loop = &main_birdloop;
+
birdloop_enter_locked(&main_birdloop);
}
static void birdloop_main(void *arg);
+void
+birdloop_free(resource *r)
+{
+ struct birdloop *loop = (void *) r;
+
+ ASSERT_DIE(loop->links == 0);
+ domain_free(loop->time.domain);
+}
+
+void
+birdloop_dump(resource *r)
+{
+ struct birdloop *loop = (void *) r;
+
+ debug("%s\n", loop->pool->name);
+}
+
+struct resclass birdloop_class = {
+ .name = "IO Loop",
+ .size = sizeof(struct birdloop),
+ .free = birdloop_free,
+ .dump = birdloop_dump,
+};
+
struct birdloop *
birdloop_new(pool *pp, uint order, const char *name)
{
struct domain_generic *dg = domain_new(name, order);
- pool *p = rp_new(pp, name);
- struct birdloop *loop = mb_allocz(p, sizeof(struct birdloop));
- loop->pool = p;
+ struct birdloop *loop = ralloc(pp, &birdloop_class);
loop->time.domain = dg;
loop->time.loop = loop;
birdloop_enter(loop);
+ loop->pool = rp_new(pp, loop, name);
+ loop->parent = pp;
+ rmove(&loop->r, loop->pool);
+
wakeup_init(loop);
ev_init_list(&loop->event_list, loop, name);
- timers_init(&loop->time, p);
+ timers_init(&loop->time, loop->pool);
sockets_init(loop);
- loop->time.coro = coro_run(p, birdloop_main, loop);
+ loop->time.coro = coro_run(loop->pool, birdloop_main, loop);
birdloop_leave(loop);
@@ -389,14 +423,6 @@ birdloop_stop_self(struct birdloop *loop, void (*stopped)(void *data), void *dat
birdloop_do_stop(loop, stopped, data);
}
-void
-birdloop_free(struct birdloop *loop)
-{
- ASSERT_DIE(loop->links == 0);
- domain_free(loop->time.domain);
- rfree(loop->pool);
-}
-
static void
birdloop_enter_locked(struct birdloop *loop)
{
@@ -529,7 +555,25 @@ birdloop_main(void *arg)
ASSERT_DIE(loop->sock_num == 0);
birdloop_leave(loop);
+
+ /* Lock parent loop */
+ pool *parent = loop->parent;
+ birdloop_enter(parent->loop);
+
+ /* Move the loop temporarily to parent pool */
+ birdloop_enter(loop);
+ rmove(&loop->r, parent);
+ birdloop_leave(loop);
+
+ /* Announce loop stop */
loop->stopped(loop->stop_data);
-}
+ /* Free the pool and loop */
+ birdloop_enter(loop);
+ rp_free(loop->pool, parent);
+ birdloop_leave(loop);
+ rfree(&loop->r);
+ /* And finally leave the parent loop before finishing */
+ birdloop_leave(parent->loop);
+}
diff --git a/sysdep/unix/io-loop.h b/sysdep/unix/io-loop.h
index 4024b6c5..3fccd520 100644
--- a/sysdep/unix/io-loop.h
+++ b/sysdep/unix/io-loop.h
@@ -9,7 +9,10 @@
struct birdloop
{
+ resource r;
+
pool *pool;
+ pool *parent;
struct timeloop time;
event_list event_list;
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 98c56391..c0f2e930 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -74,7 +74,7 @@ static list krt_proto_list;
void
krt_io_init(void)
{
- krt_pool = rp_new(&root_pool, "Kernel Syncer");
+ krt_pool = rp_new(&root_pool, &main_birdloop, "Kernel Syncer");
krt_filter_lp = lp_new_default(krt_pool);
init_list(&krt_proto_list);
krt_sys_io_init();
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 5da27cb6..ca06611f 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -52,7 +52,7 @@ async_dump(void)
{
debug("INTERNAL STATE DUMP\n\n");
- rdump(&root_pool);
+ rp_dump(&root_pool);
sk_dump_all();
// XXXX tm_dump_all();
if_dump_all();
diff --git a/test/bt-utils.c b/test/bt-utils.c
index 90815e77..98aaed3d 100644
--- a/test/bt-utils.c
+++ b/test/bt-utils.c
@@ -65,8 +65,8 @@ bt_bird_init(void)
the_bird_lock();
resource_init();
- olock_init();
birdloop_init();
+ olock_init();
io_init();
rt_init();
if_init();