summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/conf.c4
-rw-r--r--lib/hash_test.c2
-rw-r--r--lib/io-loop.h1
-rw-r--r--lib/locking.h2
-rw-r--r--lib/resource.c139
-rw-r--r--lib/resource.h34
-rw-r--r--nest/cli.c6
-rw-r--r--nest/cli.h1
-rw-r--r--nest/iface.c7
-rw-r--r--nest/locks.h1
-rw-r--r--nest/password.h2
-rw-r--r--nest/proto.c12
-rw-r--r--nest/protocol.h2
-rw-r--r--nest/rt-attr.c20
-rw-r--r--nest/rt-show.c1
-rw-r--r--nest/rt-table.c63
-rw-r--r--nest/rt.h3
-rw-r--r--proto/babel/babel.c2
-rw-r--r--proto/bfd/bfd.c2
-rw-r--r--proto/bgp/attrs.c4
-rw-r--r--proto/bgp/bgp.c3
-rw-r--r--proto/ospf/iface.c4
-rw-r--r--proto/ospf/neighbor.c2
-rw-r--r--proto/radv/radv.c2
-rw-r--r--proto/rpki/rpki.c2
-rw-r--r--sysdep/unix/io-loop.c59
-rw-r--r--sysdep/unix/krt.c2
27 files changed, 257 insertions, 125 deletions
diff --git a/conf/conf.c b/conf/conf.c
index 2cfe7b15..c7cd81fe 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -90,7 +90,7 @@ int undo_available; /* Undo was not requested from last reconfiguration */
struct config *
config_alloc(const char *name)
{
- pool *p = rp_new(config_pool, "Config");
+ pool *p = rp_new(config_pool, the_bird_domain.the_bird, "Config");
linpool *l = lp_new_default(p);
struct config *c = lp_allocz(l, sizeof(struct config));
@@ -515,7 +515,7 @@ config_timeout(timer *t UNUSED)
void
config_init(void)
{
- config_pool = rp_new(&root_pool, "Configurations");
+ config_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Configurations");
config_event = ev_new(config_pool);
config_event->hook = config_done;
diff --git a/lib/hash_test.c b/lib/hash_test.c
index ecfcdd66..30213320 100644
--- a/lib/hash_test.c
+++ b/lib/hash_test.c
@@ -61,7 +61,7 @@ dump_nodes(void)
static void
init_hash_(uint order)
{
- my_pool = rp_new(&root_pool, "Test pool");
+ my_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Test pool");
HASH_INIT(hash, my_pool, order);
diff --git a/lib/io-loop.h b/lib/io-loop.h
index b0d3d6cc..80cd2ea2 100644
--- a/lib/io-loop.h
+++ b/lib/io-loop.h
@@ -31,6 +31,7 @@ event_list *birdloop_event_list(struct birdloop *loop);
/* Get birdloop's time heap */
struct timeloop *birdloop_time_loop(struct birdloop *loop);
+#define birdloop_domain(l) (birdloop_time_loop((l))->domain)
/* Get birdloop's pool */
pool *birdloop_pool(struct birdloop *loop);
diff --git a/lib/locking.h b/lib/locking.h
index 6bed14bf..751eecbd 100644
--- a/lib/locking.h
+++ b/lib/locking.h
@@ -13,8 +13,8 @@ struct domain_generic;
/* Here define the global lock order; first to last. */
struct lock_order {
- struct domain_generic *meta;
struct domain_generic *the_bird;
+ struct domain_generic *meta;
struct domain_generic *control;
struct domain_generic *proto;
struct domain_generic *service;
diff --git a/lib/resource.c b/lib/resource.c
index b1b89bdf..2071a411 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -46,6 +46,16 @@ static struct resclass pool_class = {
pool root_pool;
+static void
+rp_init(pool *z, struct domain_generic *dom, const char *name)
+{
+ ASSERT_DIE(DG_IS_LOCKED(dom));
+
+ z->name = name;
+ z->domain = dom;
+ z->inside = (TLIST_LIST(resource)) {};
+}
+
/**
* rp_new - create a resource pool
* @p: parent pool
@@ -55,77 +65,106 @@ pool root_pool;
* parent pool.
*/
pool *
-rp_new(pool *p, const char *name)
+rp_new(pool *p, struct domain_generic *dom, const char *name)
{
pool *z = ralloc(p, &pool_class);
- z->name = name;
- init_list(&z->inside);
+
+ if (dg_order(p->domain) > dg_order(dom))
+ bug("Requested reverse order pool creation: %s (%d) can't be a parent of %s (%d)",
+ domain_name(p->domain), dg_order(p->domain),
+ domain_name(dom), dg_order(dom));
+
+ if ((dg_order(p->domain) == dg_order(dom)) && (p->domain != dom))
+ bug("Requested incomparable order pool creation: %s (%d) can't be a parent of %s (%d)",
+ domain_name(p->domain), dg_order(p->domain),
+ domain_name(dom), dg_order(dom));
+
+ rp_init(z, dom, name);
return z;
}
pool *
-rp_vnewf(pool *p, const char *fmt, va_list args)
+rp_vnewf(pool *p, struct domain_generic *dom, const char *fmt, va_list args)
{
- pool *z = rp_new(p, NULL);
+ pool *z = rp_new(p, dom, NULL);
z->name = mb_vsprintf(p, fmt, args);
return z;
}
pool *
-rp_newf(pool *p, const char *fmt, ...)
+rp_newf(pool *p, struct domain_generic *dom, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- pool *z = rp_vnewf(p, fmt, args);
+ pool *z = rp_vnewf(p, dom, fmt, args);
va_end(args);
return z;
}
+#define POOL_LOCK \
+ struct domain_generic *dom = p->domain; \
+ int locking = !DG_IS_LOCKED(dom); \
+ if (locking) \
+ DG_LOCK(dom); \
+
+#define POOL_UNLOCK if (locking) DG_UNLOCK(dom);\
+
+void rp_free(pool *p)
+{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+ rfree(p);
+}
static void
pool_free(resource *P)
{
pool *p = (pool *) P;
- resource *r, *rr;
- r = HEAD(p->inside);
- while (rr = (resource *) r->n.next)
+ POOL_LOCK;
+ WALK_TLIST_DELSAFE(resource, r, &p->inside)
{
r->class->free(r);
xfree(r);
- r = rr;
}
+ POOL_UNLOCK;
}
+
static void
pool_dump(resource *P, unsigned indent)
{
pool *p = (pool *) P;
- resource *r;
+
+ POOL_LOCK;
debug("%s\n", p->name);
- WALK_LIST(r, p->inside)
+ WALK_TLIST_DELSAFE(resource, r, &p->inside)
rdump(r, indent + 3);
+
+ POOL_UNLOCK;
}
static struct resmem
pool_memsize(resource *P)
{
pool *p = (pool *) P;
- resource *r;
struct resmem sum = {
.effective = 0,
.overhead = sizeof(pool) + ALLOC_OVERHEAD,
};
- WALK_LIST(r, p->inside)
+ POOL_LOCK;
+
+ WALK_TLIST(resource, r, &p->inside)
{
struct resmem add = rmemsize(r);
sum.effective += add.effective;
sum.overhead += add.overhead;
}
+ POOL_UNLOCK;
+
return sum;
}
@@ -133,14 +172,25 @@ static resource *
pool_lookup(resource *P, unsigned long a)
{
pool *p = (pool *) P;
- resource *r, *q;
+ resource *q = NULL;
+
+ POOL_LOCK;
- WALK_LIST(r, p->inside)
+ WALK_TLIST(resource, r, &p->inside)
if (r->class->lookup && (q = r->class->lookup(r, a)))
- return q;
- return NULL;
+ break;
+
+ POOL_UNLOCK;
+ return q;
+}
+
+static pool *
+resource_parent(resource *r)
+{
+ return SKIP_BACK(pool, inside, resource_enlisted(r));
}
+
/**
* rmove - move a resource
* @res: resource
@@ -152,13 +202,13 @@ pool_lookup(resource *P, unsigned long a)
void rmove(void *res, pool *p)
{
resource *r = res;
+ pool *orig = resource_parent(r);
- if (r)
- {
- if (r->n.next)
- rem_node(&r->n);
- add_tail(&p->inside, &r->n);
- }
+ ASSERT_DIE(DG_IS_LOCKED(orig->domain));
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
+ resource_rem_node(&orig->inside, r);
+ resource_add_tail(&p->inside, r);
}
/**
@@ -179,8 +229,10 @@ rfree(void *res)
if (!r)
return;
- if (r->n.next)
- rem_node(&r->n);
+ pool *orig = resource_parent(r);
+ ASSERT_DIE(DG_IS_LOCKED(orig->domain));
+ resource_rem_node(&orig->inside, r);
+
r->class->free(r);
r->class = NULL;
xfree(r);
@@ -239,12 +291,14 @@ rmemsize(void *res)
void *
ralloc(pool *p, struct resclass *c)
{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
resource *r = xmalloc(c->size);
bzero(r, c->size);
r->class = c;
- if (p)
- add_tail(&p->inside, &r->n);
+ resource_add_tail(&p->inside, r);
+
return r;
}
@@ -284,28 +338,29 @@ resource_init(void)
rcu_init();
resource_sys_init();
- root_pool.r.class = &pool_class;
- root_pool.name = "Root";
- init_list(&root_pool.inside);
- tmp_init(&root_pool);
+ rp_init(&root_pool, the_bird_domain.the_bird, "Root");
+ tmp_init(&root_pool, the_bird_domain.the_bird);
}
_Thread_local struct tmp_resources tmp_res;
void
-tmp_init(pool *p)
+tmp_init(pool *p, struct domain_generic *dom)
{
tmp_res.lp = lp_new_default(p);
tmp_res.parent = p;
- tmp_res.pool = rp_new(p, "TMP");
+ tmp_res.pool = rp_new(p, dom, "TMP");
+ tmp_res.domain = dom;
}
void
tmp_flush(void)
{
+ ASSERT_DIE(DG_IS_LOCKED(tmp_res.domain));
+
lp_flush(tmp_linpool);
rp_free(tmp_res.pool);
- tmp_res.pool = rp_new(tmp_res.parent, "TMP");
+ tmp_res.pool = rp_new(tmp_res.parent, tmp_res.domain, "TMP");
}
@@ -385,11 +440,13 @@ static struct resclass mb_class = {
void *
mb_alloc(pool *p, unsigned size)
{
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
+
struct mblock *b = xmalloc(sizeof(struct mblock) + size);
b->r.class = &mb_class;
- b->r.n = (node) {};
- add_tail(&p->inside, &b->r.n);
+ b->r.n = (struct resource_node) {};
+ resource_add_tail(&p->inside, &b->r);
b->size = size;
return b->data;
}
@@ -434,10 +491,14 @@ void *
mb_realloc(void *m, unsigned size)
{
struct mblock *b = SKIP_BACK(struct mblock, data, m);
+ struct pool *p = resource_parent(&b->r);
+
+ ASSERT_DIE(DG_IS_LOCKED(p->domain));
b = xrealloc(b, sizeof(struct mblock) + size);
- update_node(&b->r.n);
b->size = size;
+
+ resource_update_node(&p->inside, &b->r);
return b->data;
}
diff --git a/lib/resource.h b/lib/resource.h
index 2adb9de0..810334c1 100644
--- a/lib/resource.h
+++ b/lib/resource.h
@@ -10,7 +10,8 @@
#ifndef _BIRD_RESOURCE_H_
#define _BIRD_RESOURCE_H_
-#include "lib/lists.h"
+#include "lib/locking.h"
+#include "lib/tlists.h"
#include <stdarg.h>
@@ -21,11 +22,20 @@ struct resmem {
/* Resource */
+#define TLIST_PREFIX resource
+#define TLIST_TYPE struct resource
+#define TLIST_ITEM n
+#define TLIST_WANT_WALK
+#define TLIST_WANT_ADD_TAIL
+#define TLIST_WANT_UPDATE_NODE
+
typedef struct resource {
- node n; /* Inside resource pool */
- struct resclass *class; /* Resource class */
+ TLIST_DEFAULT_NODE; /* Inside resource pool */
+ const struct resclass *class; /* Resource class */
} resource;
+#include "lib/tlists.h"
+
/* Resource class */
struct resclass {
@@ -44,14 +54,13 @@ struct resclass {
typedef struct pool {
resource r;
- list inside;
+ TLIST_LIST(resource) inside;
+ struct domain_generic *domain;
const char *name;
} pool;
void resource_init(void);
-pool *rp_new(pool *, const char *); /* Create new pool */
-pool *rp_newf(pool *, const char *, ...); /* Create a new pool with a formatted string as its name */
void rfree(void *); /* Free single resource */
void rdump(void *, unsigned indent); /* Dump to debug output */
struct resmem rmemsize(void *res); /* Return size of memory used by the resource */
@@ -60,12 +69,10 @@ void rmove(void *, pool *); /* Move to a different pool */
void *ralloc(pool *, struct resclass *);
-pool *rp_new(pool *, const char *); /* Create a new pool */
-pool *rp_newf(pool *, const char *, ...); /* Create a new pool with a formatted string as its name */
-pool *rp_vnewf(pool *, const char *, va_list); /* Create a new pool with a formatted string as its name */
-void rp_init(pool *, const char *); /* Init a new pool */
-void rp_initf(pool *, const char *, ...); /* Init a new pool with a formatted string as its name */
-static inline void rp_free(pool *p) { rfree(&p->r); } /* Free the whole pool */
+pool *rp_new(pool *, struct domain_generic *, const char *); /* Create a new pool */
+pool *rp_newf(pool *, struct domain_generic *, const char *, ...); /* Create a new pool with a formatted string as its name */
+pool *rp_vnewf(pool *, struct domain_generic *, const char *, va_list); /* Create a new pool with a formatted string as its name */
+void rp_free(pool *p); /* Free the whole pool */
extern pool root_pool;
@@ -97,6 +104,7 @@ void lp_restore(linpool *m, lp_state *p); /* Restore state */
struct tmp_resources {
pool *pool, *parent;
linpool *lp;
+ struct domain_generic *domain;
};
extern _Thread_local struct tmp_resources tmp_res;
@@ -106,7 +114,7 @@ extern _Thread_local struct tmp_resources tmp_res;
#define tmp_allocu(sz) lp_allocu(tmp_linpool, sz)
#define tmp_allocz(sz) lp_allocz(tmp_linpool, sz)
-void tmp_init(pool *p);
+void tmp_init(pool *p, struct domain_generic *dg);
void tmp_flush(void);
diff --git a/nest/cli.c b/nest/cli.c
index 29591d26..b74edffb 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, the_bird_domain.the_bird, "Config");
init_list(&f.symbols);
cf_read_hook = cli_cmd_read_hook;
cli_rh_pos = c->rx_buf;
@@ -309,7 +309,7 @@ cli_event(void *data)
cli *
cli_new(struct birdsock *sock)
{
- pool *p = rp_new(cli_pool, "CLI");
+ pool *p = rp_new(cli_pool, the_bird_domain.the_bird, "CLI");
cli *c = mb_alloc(p, sizeof(cli));
bzero(c, sizeof(cli));
@@ -433,7 +433,7 @@ cli_free(cli *c)
void
cli_init(void)
{
- cli_pool = rp_new(&root_pool, "CLI");
+ cli_pool = rp_new(&root_pool, the_bird_domain.the_bird, "CLI");
init_list(&cli_log_hooks);
cli_log_inited = 1;
}
diff --git a/nest/cli.h b/nest/cli.h
index 2d876571..c5cbd8d7 100644
--- a/nest/cli.h
+++ b/nest/cli.h
@@ -10,6 +10,7 @@
#define _BIRD_CLI_H_
#include "lib/resource.h"
+#include "lib/lists.h"
#include "lib/event.h"
#define CLI_RX_BUF_SIZE 4096
diff --git a/nest/iface.c b/nest/iface.c
index f1938664..a024b943 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -1018,12 +1018,15 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
void
if_init(void)
{
- if_pool = rp_new(&root_pool, "Interfaces");
+ iface_domain = DOMAIN_NEW(attrs, "Interfaces");
+
+ IFACE_LOCK;
+ if_pool = rp_new(&root_pool, iface_domain.attrs, "Interfaces");
init_list(&global_iface_list);
iface_sub_slab = sl_new(if_pool, sizeof(struct iface_notification));
strcpy(default_vrf.name, "default");
neigh_init(if_pool);
- iface_domain = DOMAIN_NEW(attrs, "Interfaces");
+ IFACE_UNLOCK;
}
/*
diff --git a/nest/locks.h b/nest/locks.h
index 04571e69..993e296b 100644
--- a/nest/locks.h
+++ b/nest/locks.h
@@ -10,6 +10,7 @@
#define _BIRD_LOCKS_H_
#include "lib/resource.h"
+#include "lib/lists.h"
#include "lib/event.h"
/*
diff --git a/nest/password.h b/nest/password.h
index 53168bb7..335b9cd4 100644
--- a/nest/password.h
+++ b/nest/password.h
@@ -10,6 +10,8 @@
#ifndef PASSWORD_H
#define PASSWORD_H
+#include "lib/lists.h"
+
struct password_item {
node n;
const char *password; /* Key data, null terminated */
diff --git a/nest/proto.c b/nest/proto.c
index d6269272..32183c9d 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -367,6 +367,7 @@ channel_roa_subscribe(struct channel *c, rtable *tab, int dir)
.name = mb_sprintf(c->proto->pool, "%s.%s.roa-%s.%s",
c->proto->name, c->name, dir ? "in" : "out", tab->name),
.list = proto_work_list(c->proto),
+ .pool = c->proto->pool,
.trace_routes = c->debug | c->proto->debug,
.dump_req = channel_dump_roa_req,
.export_one = channel_export_one_roa,
@@ -495,6 +496,7 @@ channel_start_export(struct channel *c)
c->out_req = (struct rt_export_request) {
.name = mb_sprintf(c->proto->pool, "%s.%s", c->proto->name, c->name),
.list = proto_work_list(c->proto),
+ .pool = c->proto->pool,
.addr = c->out_subprefix,
.addr_mode = c->out_subprefix ? TE_ADDR_IN : TE_ADDR_NONE,
.trace_routes = c->debug | c->proto->debug,
@@ -685,6 +687,7 @@ channel_setup_in_table(struct channel *c)
c->reload_req = (struct rt_export_request) {
.name = mb_sprintf(c->proto->pool, "%s.%s.import", c->proto->name, c->name),
.list = proto_work_list(c->proto),
+ .pool = c->proto->pool,
.trace_routes = c->debug | c->proto->debug,
.export_bulk = channel_reload_export_bulk,
.dump_req = channel_reload_dump_req,
@@ -1132,15 +1135,14 @@ proto_loop_stopped(void *ptr)
{
struct proto *p = ptr;
- birdloop_enter(&main_birdloop);
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
+ ASSERT_DIE(p->loop != &main_birdloop);
p->pool = NULL; /* is freed by birdloop_free() */
birdloop_free(p->loop);
p->loop = &main_birdloop;
proto_cleanup(p);
-
- birdloop_leave(&main_birdloop);
}
static void
@@ -1228,7 +1230,7 @@ proto_start(struct proto *p)
p->pool = birdloop_pool(p->loop);
}
else
- p->pool = rp_newf(proto_pool, "Protocol %s", p->cf->name);
+ p->pool = rp_newf(proto_pool, the_bird_domain.the_bird, "Protocol %s", p->cf->name);
p->iface_sub.target = proto_event_list(p);
@@ -1859,7 +1861,7 @@ protos_build(void)
{
protos_build_gen();
- proto_pool = rp_new(&root_pool, "Protocols");
+ proto_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Protocols");
}
diff --git a/nest/protocol.h b/nest/protocol.h
index eccfcb73..02ec5c15 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -280,6 +280,8 @@ struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, st
#define PROTO_LOCKED_FROM_MAIN(p) for (struct birdloop *_proto_loop = PROTO_ENTER_FROM_MAIN(p); _proto_loop; PROTO_LEAVE_FROM_MAIN(_proto_loop), (_proto_loop = NULL))
+static inline struct domain_generic *proto_domain(struct proto *p)
+{ return birdloop_domain(p->loop); }
#define CMD_RELOAD 0
#define CMD_RELOAD_IN 1
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 903926f6..38612a4e 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -605,9 +605,16 @@ ea_register(pool *p, struct ea_class *def)
struct ea_class_ref *
ea_register_alloc(pool *p, struct ea_class cl)
{
+ struct ea_class_ref *ref;
+
+ RTA_LOCK;
struct ea_class *clp = ea_class_find_by_name(cl.name);
if (clp && clp->type == cl.type)
- return ea_ref_class(p, clp);
+ {
+ ref = ea_ref_class(p, clp);
+ RTA_UNLOCK;
+ return ref;
+ }
uint namelen = strlen(cl.name) + 1;
@@ -619,14 +626,18 @@ ea_register_alloc(pool *p, struct ea_class cl)
memcpy(cla->name, cl.name, namelen);
cla->cl.name = cla->name;
- return ea_register(p, &cla->cl);
+ ref = ea_register(p, &cla->cl);
+ RTA_UNLOCK;
+ return ref;
}
void
ea_register_init(struct ea_class *clp)
{
+ RTA_LOCK;
ASSERT_DIE(!ea_class_find_by_name(clp->name));
ea_register(&root_pool, clp);
+ RTA_UNLOCK;
}
struct ea_class *
@@ -1598,7 +1609,8 @@ rta_init(void)
{
attrs_domain = DOMAIN_NEW(attrs, "Attributes");
- rta_pool = rp_new(&root_pool, "Attributes");
+ RTA_LOCK;
+ rta_pool = rp_new(&root_pool, attrs_domain.attrs, "Attributes");
for (uint i=0; i<ARRAY_SIZE(ea_slab_sizes); i++)
ea_slab[i] = sl_new(rta_pool, ea_slab_sizes[i]);
@@ -1607,6 +1619,8 @@ rta_init(void)
rte_src_init();
ea_class_init();
+ RTA_UNLOCK;
+
/* These attributes are required to be first for nice "show route" output */
ea_register_init(&ea_gen_nexthop);
ea_register_init(&ea_gen_hostentry);
diff --git a/nest/rt-show.c b/nest/rt-show.c
index eacd4e31..7a8b629b 100644
--- a/nest/rt-show.c
+++ b/nest/rt-show.c
@@ -288,6 +288,7 @@ rt_show_cont(struct rt_show_data *d)
.addr = d->addr,
.name = "CLI Show Route",
.list = &global_work_list,
+ .pool = c->pool,
.export_bulk = rt_show_net_export_bulk,
.dump_req = rt_show_dump_req,
.log_state_change = rt_show_log_state_change,
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 9629db2c..f1e3c8f7 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -2131,7 +2131,7 @@ rt_table_export_start_locked(struct rtable_private *tab, struct rt_export_reques
struct rt_exporter *re = &tab->exporter.e;
rt_lock_table(tab);
- req->hook = rt_alloc_export(re, sizeof(struct rt_table_export_hook));
+ req->hook = rt_alloc_export(re, req->pool, sizeof(struct rt_table_export_hook));
req->hook->req = req;
struct rt_table_export_hook *hook = SKIP_BACK(struct rt_table_export_hook, h, req->hook);
@@ -2212,9 +2212,9 @@ rt_request_export_other(struct rt_exporter *re, struct rt_export_request *req)
}
struct rt_export_hook *
-rt_alloc_export(struct rt_exporter *re, uint size)
+rt_alloc_export(struct rt_exporter *re, pool *pp, uint size)
{
- pool *p = rp_new(re->rp, "Export hook");
+ pool *p = rp_new(pp, pp->domain, "Export hook");
struct rt_export_hook *hook = mb_allocz(p, size);
hook->pool = p;
@@ -2709,13 +2709,14 @@ rt_flowspec_link(rtable *src_pub, rtable *dst_pub)
if (!ln)
{
- pool *p = src->rp;
+ pool *p = birdloop_pool(dst_pub->loop);
ln = mb_allocz(p, sizeof(struct rt_flowspec_link));
ln->src = src_pub;
ln->dst = dst_pub;
ln->req = (struct rt_export_request) {
.name = mb_sprintf(p, "%s.flowspec.notifier", dst_pub->name),
.list = birdloop_event_list(dst_pub->loop),
+ .pool = p,
.trace_routes = src->config->debug,
.dump_req = rt_flowspec_dump_req,
.log_state_change = rt_flowspec_log_state_change,
@@ -2781,8 +2782,6 @@ rt_free(resource *_r)
{
struct rtable_private *r = SKIP_BACK(struct rtable_private, r, _r);
- DOMAIN_FREE(rtable, r->lock);
-
DBG("Deleting routing table %s\n", r->name);
ASSERT_DIE(r->use_count == 0);
@@ -2847,13 +2846,20 @@ rt_setup(pool *pp, struct rtable_config *cf)
/* Start the service thread */
struct birdloop *loop = birdloop_new(pp, DOMAIN_ORDER(service), 0, "Routing table service %s", cf->name);
+ birdloop_enter(loop);
pool *sp = birdloop_pool(loop);
- pool *p = rp_newf(sp, "Routing table data %s", cf->name);
+
+ /* Create the table domain and pool */
+ DOMAIN(rtable) dom = DOMAIN_NEW(rtable, cf->name);
+ LOCK_DOMAIN(rtable, dom);
+
+ pool *p = rp_newf(sp, dom.rtable, "Routing table data %s", cf->name);
/* Create the actual table */
struct rtable_private *t = ralloc(p, &rt_class);
t->rp = p;
t->loop = loop;
+ t->lock = dom;
t->rte_slab = sl_new(p, sizeof(struct rte_storage));
@@ -2864,8 +2870,6 @@ rt_setup(pool *pp, struct rtable_config *cf)
if (t->id >= rtable_max_id)
rtable_max_id = t->id + 1;
- t->lock = DOMAIN_NEW(rtable, t->name);
-
fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL);
if (cf->trie_used)
@@ -2911,8 +2915,9 @@ rt_setup(pool *pp, struct rtable_config *cf)
t->flowspec_trie->ipv4 = (t->addr_type == NET_FLOW4);
}
+ UNLOCK_DOMAIN(rtable, dom);
+
/* Setup the service thread flag handler */
- birdloop_enter(t->loop);
birdloop_flag_set_handler(t->loop, &t->fh);
birdloop_leave(t->loop);
@@ -2929,7 +2934,7 @@ void
rt_init(void)
{
rta_init();
- rt_table_pool = rp_new(&root_pool, "Routing tables");
+ rt_table_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Routing tables");
init_list(&routing_tables);
init_list(&deleted_routing_tables);
ev_init_list(&rt_cork.queue, &main_birdloop, "Route cork release");
@@ -4067,13 +4072,14 @@ rt_shutdown(void *tab_)
static void
rt_delete(void *tab_)
{
- birdloop_enter(&main_birdloop);
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
/* We assume that nobody holds the table reference now as use_count is zero.
* Anyway the last holder may still hold the lock. Therefore we lock and
* unlock it the last time to be sure that nobody is there. */
struct rtable_private *tab = RT_LOCK((rtable *) tab_);
struct config *conf = tab->deleted;
+ DOMAIN(rtable) dom = tab->lock;
RT_UNLOCK(RT_PUB(tab));
@@ -4081,7 +4087,8 @@ rt_delete(void *tab_)
birdloop_free(tab->loop);
config_del_obstacle(conf);
- birdloop_leave(&main_birdloop);
+ /* Also drop the domain */
+ DOMAIN_FREE(rtable, dom);
}
@@ -4636,18 +4643,9 @@ rt_init_hostcache(struct rtable_private *tab)
.data = tab,
};
- hc->req = (struct rt_export_request) {
- .name = mb_sprintf(tab->rp, "%s.hcu.notifier", tab->name),
- .list = birdloop_event_list(tab->loop),
- .trace_routes = tab->config->debug,
- .dump_req = hc_notify_dump_req,
- .log_state_change = hc_notify_log_state_change,
- .export_one = hc_notify_export_one,
- };
-
- rt_table_export_start_locked(tab, &hc->req);
-
tab->hostcache = hc;
+
+ ev_send_loop(tab->loop, &hc->update);
}
static void
@@ -4775,9 +4773,24 @@ rt_update_hostcache(void *data)
RT_LOCKED((rtable *) data, tab)
{
-
struct hostcache *hc = tab->hostcache;
+ /* Finish initialization */
+ if (!hc->req.name)
+ {
+ hc->req = (struct rt_export_request) {
+ .name = mb_sprintf(tab->rp, "%s.hcu.notifier", tab->name),
+ .list = birdloop_event_list(tab->loop),
+ .pool = tab->rp,
+ .trace_routes = tab->config->debug,
+ .dump_req = hc_notify_dump_req,
+ .log_state_change = hc_notify_log_state_change,
+ .export_one = hc_notify_export_one,
+ };
+
+ rt_table_export_start_locked(tab, &hc->req);
+ }
+
/* Shutdown shortcut */
if (!hc->req.hook)
RT_RETURN(tab);
diff --git a/nest/rt.h b/nest/rt.h
index 01372b8c..4fe8eb53 100644
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -294,6 +294,7 @@ struct rt_export_request {
u8 addr_mode; /* Network prefilter mode (TE_ADDR_*) */
event_list *list; /* Where to schedule export events */
+ pool *pool; /* Pool to use for allocations */
/* There are two methods of export. You can either request feeding every single change
* or feeding the whole route feed. In case of regular export, &export_one is preferred.
@@ -438,7 +439,7 @@ int rpe_get_seen(struct rt_export_hook *hook, struct rt_pending_export *rpe);
*/
void rt_init_export(struct rt_exporter *re, struct rt_export_hook *hook);
-struct rt_export_hook *rt_alloc_export(struct rt_exporter *re, uint size);
+struct rt_export_hook *rt_alloc_export(struct rt_exporter *re, pool *pool, uint size);
void rt_stop_export_common(struct rt_export_hook *hook);
void rt_export_stopped(struct rt_export_hook *hook);
void rt_exporter_init(struct rt_exporter *re);
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index e95a0ead..decaa407 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1826,7 +1826,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, proto_domain(&p->p), 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 ddbc4948..f7d8f8d9 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -1073,7 +1073,7 @@ bfd_start(struct proto *P)
pthread_spin_init(&p->lock, PTHREAD_PROCESS_PRIVATE);
- p->tpool = rp_new(P->pool, "BFD loop pool");
+ p->tpool = birdloop_pool(P->loop);
p->session_slab = sl_new(P->pool, sizeof(struct bfd_session));
HASH_INIT(p->session_hash_id, P->pool, 8);
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 4e6524f4..82971c01 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1853,7 +1853,7 @@ bgp_init_pending_tx(struct bgp_channel *c)
{
ASSERT_DIE(!c->ptx);
- pool *p = rp_new(c->pool, "BGP Pending TX");
+ pool *p = rp_new(c->pool, proto_domain(c->c.proto), "BGP Pending TX");
c->ptx = ralloc(p, &bgp_pending_tx_class);
c->ptx->pool = p;
@@ -1981,7 +1981,7 @@ bgp_out_table_feed(void *data)
static void
bgp_out_table_export_start(struct rt_exporter *re, struct rt_export_request *req)
{
- req->hook = rt_alloc_export(re, sizeof(struct bgp_out_export_hook));
+ req->hook = rt_alloc_export(re, req->pool, sizeof(struct bgp_out_export_hook));
req->hook->req = req;
struct bgp_out_export_hook *hook = SKIP_BACK(struct bgp_out_export_hook, h, req->hook);
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 0525d502..e60884ba 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -922,7 +922,8 @@ bgp_graceful_restart_feed(struct bgp_channel *c)
{
c->stale_feed = (struct rt_export_request) {
.name = "BGP-GR",
- .list = &global_work_list,
+ .list = proto_event_list(c->c.proto),
+ .pool = c->c.proto->pool,
.trace_routes = c->c.debug | c->c.proto->debug,
.dump_req = bgp_graceful_restart_feed_dump_req,
.log_state_change = bgp_graceful_restart_feed_log_state_change,
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 0eecb432..c3ec4a4c 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -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, proto_domain(&p->p), "OSPF Interface");
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
ifa->iface = iface;
ifa->addr = addr;
@@ -690,7 +690,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, proto_domain(&p->p), "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 2c73d251..59a60587 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, proto_domain(&p->p), "OSPF Neighbor");
struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
n->pool = pool;
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index eb15f9cb..3d5fe5a3 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -287,7 +287,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, proto_domain(&p->p), iface->name);
ifa = mb_allocz(pool, sizeof(struct radv_iface));
ifa->pool = pool;
ifa->ra = p;
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index e5638aff..0fd686b3 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -599,7 +599,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, proto_domain(&p->p), 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 701eddf7..8e95a698 100644
--- a/sysdep/unix/io-loop.c
+++ b/sysdep/unix/io-loop.c
@@ -503,12 +503,14 @@ sockets_fire(struct birdloop *loop)
*/
DEFINE_DOMAIN(resource);
+static void bird_thread_start_event(void *_data);
struct birdloop_pickup_group {
DOMAIN(resource) domain;
list loops;
list threads;
btime max_latency;
+ event start_threads;
} pickup_groups[2] = {
{
/* all zeroes */
@@ -516,6 +518,8 @@ struct birdloop_pickup_group {
{
/* FIXME: make this dynamic, now it copies the loop_max_latency value from proto/bfd/config.Y */
.max_latency = 10 MS,
+ .start_threads.hook = bird_thread_start_event,
+ .start_threads.data = &pickup_groups[1],
},
};
@@ -630,13 +634,11 @@ bird_thread_main(void *arg)
rcu_thread_start(&thr->rcu);
synchronize_rcu();
- tmp_init(thr->pool);
- init_list(&thr->loops);
-
- thr->meta = birdloop_new_no_pickup(thr->pool, DOMAIN_ORDER(meta), "Thread Meta");
- thr->meta->thread = thr;
birdloop_enter(thr->meta);
+ tmp_init(thr->pool, birdloop_domain(thr->meta));
+ init_list(&thr->loops);
+
thr->sock_changed = 1;
struct pfd pfd;
@@ -759,15 +761,20 @@ static struct bird_thread *
bird_thread_start(struct birdloop_pickup_group *group)
{
ASSERT_DIE(birdloop_inside(&main_birdloop));
- ASSERT_DIE(DOMAIN_IS_LOCKED(resource, group->domain));
- pool *p = rp_new(&root_pool, "Thread");
+ struct birdloop *meta = birdloop_new_no_pickup(&root_pool, DOMAIN_ORDER(meta), "Thread Meta");
+ pool *p = birdloop_pool(meta);
+
+ birdloop_enter(meta);
+ LOCK_DOMAIN(resource, group->domain);
struct bird_thread *thr = mb_allocz(p, sizeof(*thr));
thr->pool = p;
thr->cleanup_event = (event) { .hook = bird_thread_cleanup, .data = thr, };
thr->group = group;
thr->max_latency_ns = (group->max_latency ?: 5 S) TO_NS;
+ thr->meta = meta;
+ thr->meta->thread = thr;
wakeup_init(thr);
ev_init_list(&thr->priority_events, NULL, "Thread direct event list");
@@ -790,9 +797,18 @@ bird_thread_start(struct birdloop_pickup_group *group)
if (e = pthread_create(&thr->thread_id, &thr->thread_attr, bird_thread_main, thr))
die("pthread_create() failed: %M", e);
+ UNLOCK_DOMAIN(resource, group->domain);
+ birdloop_leave(meta);
return thr;
}
+static void
+bird_thread_start_event(void *_data)
+{
+ struct birdloop_pickup_group *group = _data;
+ bird_thread_start(group);
+}
+
static struct birdloop *thread_dropper;
static event *thread_dropper_event;
static uint thread_dropper_goal;
@@ -880,15 +896,14 @@ bird_thread_commit(struct config *new, struct config *old UNUSED)
int dif = list_length(&group->threads) - (thread_dropper_goal = new->thread_count);
_Bool thread_dropper_running = !!thread_dropper;
+ UNLOCK_DOMAIN(resource, group->domain);
+
if (dif < 0)
{
bird_thread_start(group);
- UNLOCK_DOMAIN(resource, group->domain);
continue;
}
- UNLOCK_DOMAIN(resource, group->domain);
-
if ((dif > 0) && !thread_dropper_running)
{
struct birdloop *tdl = birdloop_new(&root_pool, DOMAIN_ORDER(control), group->max_latency, "Thread dropper");
@@ -1006,12 +1021,13 @@ bird_thread_show(void *data)
void
cmd_show_threads(int show_loops)
{
- pool *p = rp_new(&root_pool, "Show Threads");
+ DOMAIN(control) lock = DOMAIN_NEW(control, "Show Threads");
+ pool *p = rp_new(&root_pool, lock.control, "Show Threads");
struct bird_thread_show_data *tsd = mb_allocz(p, sizeof(struct bird_thread_show_data));
- tsd->lock = DOMAIN_NEW(control, "Show Threads");
tsd->cli = this_cli;
tsd->pool = p;
+ tsd->lock = lock;
tsd->show_loops = show_loops;
this_cli->cont = bird_thread_show_cli_cont;
@@ -1112,8 +1128,10 @@ birdloop_stop_internal(struct birdloop *loop)
/* Request local socket reload */
this_thread->sock_changed++;
- /* Tail-call the stopped hook */
- loop->stopped(loop->stop_data);
+ /* Call the stopped hook from the main loop */
+ loop->event.hook = loop->stopped;
+ loop->event.data = loop->stop_data;
+ ev_send_loop(&main_birdloop, &loop->event);
}
static void
@@ -1187,8 +1205,9 @@ static struct birdloop *
birdloop_vnew_internal(pool *pp, uint order, struct birdloop_pickup_group *group, const char *name, va_list args)
{
struct domain_generic *dg = domain_new(name, order);
+ DG_LOCK(dg);
- pool *p = rp_vnewf(pp, name, args);
+ pool *p = rp_vnewf(pp, dg, name, args);
struct birdloop *loop = mb_allocz(p, sizeof(struct birdloop));
loop->pool = p;
@@ -1197,7 +1216,7 @@ birdloop_vnew_internal(pool *pp, uint order, struct birdloop_pickup_group *group
atomic_store_explicit(&loop->thread_transition, 0, memory_order_relaxed);
- birdloop_enter(loop);
+ birdloop_enter_locked(loop);
ev_init_list(&loop->event_list, loop, name);
timers_init(&loop->time, p);
@@ -1211,8 +1230,7 @@ birdloop_vnew_internal(pool *pp, uint order, struct birdloop_pickup_group *group
LOCK_DOMAIN(resource, group->domain);
add_tail(&group->loops, &loop->n);
if (EMPTY_LIST(group->threads))
- bird_thread_start(group);
-
+ ev_send(&global_event_list, &group->start_threads);
wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads)));
UNLOCK_DOMAIN(resource, group->domain);
}
@@ -1277,8 +1295,11 @@ birdloop_free(struct birdloop *loop)
{
ASSERT_DIE(loop->thread == NULL);
- domain_free(loop->time.domain);
+ struct domain_generic *dg = loop->time.domain;
+ DG_LOCK(dg);
rp_free(loop->pool);
+ DG_UNLOCK(dg);
+ domain_free(dg);
}
static void
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 9e6ddb45..6e94b0b6 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, the_bird_domain.the_bird, "Kernel Syncer");
krt_filter_lp = lp_new_default(krt_pool);
init_list(&krt_proto_list);
krt_sys_io_init();