#define _BIRD_LOCKING_H_
struct domain_generic;
+struct pool;
/* Here define the global lock order; first to last. */
struct lock_order {
#define DEFINE_DOMAIN(type) DOMAIN(type) { struct domain_generic *type; }
#define DOMAIN_ORDER(type) OFFSETOF(struct lock_order, type)
-#define DOMAIN_NEW(type, name) (DOMAIN(type)) { .type = domain_new(name, DOMAIN_ORDER(type)) }
-struct domain_generic *domain_new(const char *name, uint order);
+#define DOMAIN_NEW(type) (DOMAIN(type)) { .type = domain_new(DOMAIN_ORDER(type)) }
+struct domain_generic *domain_new(uint order);
#define DOMAIN_FREE(type, d) domain_free((d).type)
void domain_free(struct domain_generic *);
#define DOMAIN_NAME(type, d) domain_name((d).type)
const char *domain_name(struct domain_generic *);
+#define DOMAIN_SETUP(type, d, n, p) domain_setup((d).type, n, p)
+void domain_setup(struct domain_generic *, const char *name, struct pool *);
+
#define DOMAIN_NULL(type) (DOMAIN(type)) {}
#define LOCK_DOMAIN(type, d) do_lock(((d).type), &(locking_stack.type))
void
rcu_init(void)
{
- rcu_domain = DOMAIN_NEW(resource, "Read-Copy-Update");
+ rcu_domain = DOMAIN_NEW(resource);
+ DOMAIN_SETUP(resource, rcu_domain, "Read-Copy-Update", NULL);
init_list(&rcu_thread_list);
rcu_thread_start(&main_rcu_thread);
}
{
ASSERT_DIE(DG_IS_LOCKED(dom));
+ if (name && !domain_name(dom))
+ domain_setup(dom, name, z);
+
z->name = name;
z->domain = dom;
z->inside = (TLIST_LIST(resource)) {};
rp_vnewf(pool *p, struct domain_generic *dom, const char *fmt, va_list args)
{
pool *z = rp_new(p, dom, NULL);
- z->name = mb_vsprintf(p, fmt, args);
+ z->name = mb_vsprintf(z, fmt, args);
+ if (!domain_name(dom))
+ domain_setup(dom, z->name, z);
return z;
}
void
if_init(void)
{
- iface_domain = DOMAIN_NEW(attrs, "Interfaces");
+ iface_domain = DOMAIN_NEW(attrs);
IFACE_LOCK;
if_pool = rp_new(&root_pool, iface_domain.attrs, "Interfaces");
{
DBG("olock: init\n");
init_list(&olock_list);
- olock_domain = DOMAIN_NEW(attrs, "Object lock");
+ olock_domain = DOMAIN_NEW(attrs);
+ DOMAIN_SETUP(attrs, olock_domain, "Object lock", NULL);
}
void
protos_build(void)
{
- protos_build_gen();
-
proto_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Protocols");
+
+ protos_build_gen();
}
void
rta_init(void)
{
- attrs_domain = DOMAIN_NEW(attrs, "Attributes");
+ attrs_domain = DOMAIN_NEW(attrs);
RTA_LOCK;
rta_pool = rp_new(&root_pool, attrs_domain.attrs, "Attributes");
pool *sp = birdloop_pool(loop);
/* Create the table domain and pool */
- DOMAIN(rtable) dom = DOMAIN_NEW(rtable, cf->name);
+ DOMAIN(rtable) dom = DOMAIN_NEW(rtable);
LOCK_DOMAIN(rtable, dom);
pool *p = rp_newf(sp, dom.rtable, "Routing table data %s", cf->name);
{
proto_build(&proto_bfd);
- bfd_global.lock = DOMAIN_NEW(rtable, "BFD Global");
+ bfd_global.lock = DOMAIN_NEW(rtable);
+ DOMAIN_SETUP(rtable, bfd_global.lock, "BFD Global", NULL);
+
init_list(&bfd_global.wait_list);
init_list(&bfd_global.pickup_list);
init_list(&bfd_global.proto_list);
static list STATIC_LIST_INIT(bgp_listen_pending); /* Global list of listening socket open requests */
static event bgp_listen_event = { .hook = bgp_listen_create };
-DOMAIN(rtable) bgp_listen_domain;
+static DOMAIN(rtable) bgp_listen_domain;
+static pool *bgp_listen_pool;
static void bgp_connect(struct bgp_proto *p);
static void bgp_active(struct bgp_proto *p);
{
/* Allocating new socket from global protocol pool.
* We can do this in main_birdloop. */
- sock *sk = sk_new(proto_pool);
+ sock *sk = sk_new(bgp_listen_pool);
sk->type = SK_TCP_PASSIVE;
sk->ttl = 255;
sk->saddr = req->addr;
continue;
}
- bs = mb_allocz(proto_pool, sizeof(struct bgp_socket));
+ bs = mb_allocz(bgp_listen_pool, sizeof(struct bgp_socket));
bs->sk = sk;
sk->data = bs;
{
log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport);
+ LOCK_DOMAIN(rtable, bgp_listen_domain);
sk_close(sk);
+ UNLOCK_DOMAIN(rtable, bgp_listen_domain);
return 0;
}
bgp_close_conn(&p->incoming_conn);
}
+ LOCK_DOMAIN(rtable, bgp_listen_domain);
+
BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s",
sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL,
sk->dport, acc ? "accepted" : "rejected");
sk_close(sk);
leave:
+ UNLOCK_DOMAIN(rtable, bgp_listen_domain);
birdloop_leave(p->p.loop);
return 0;
}
{
proto_build(&proto_bgp);
bgp_register_attrs();
- bgp_listen_domain = DOMAIN_NEW(rtable, "BGP Listen Sockets");
+ bgp_listen_domain = DOMAIN_NEW(rtable);
+ LOCK_DOMAIN(rtable, bgp_listen_domain);
+ bgp_listen_pool = rp_new(proto_pool, bgp_listen_domain.rtable, "BGP Listen Sockets");
+ UNLOCK_DOMAIN(rtable, bgp_listen_domain);
}
/* We assume that page size has only one bit and is between 1K and 256K (incl.).
* Otherwise, the assumptions in lib/slab.c (sl_head's num_full range) aren't met. */
- empty_pages_domain = DOMAIN_NEW(resource, "Empty Pages");
+ empty_pages_domain = DOMAIN_NEW(resource);
+ DOMAIN_SETUP(resource, empty_pages_domain, "Empty Pages", NULL);
initialized = 1;
return;
}
struct domain_generic **prev;
struct lock_order *locked_by;
const char *name;
+ pool *pool;
};
-#define DOMAIN_INIT(_name, _order) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name, .order = _order }
+#define DOMAIN_INIT(_order) { .mutex = PTHREAD_MUTEX_INITIALIZER, .order = _order }
-static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD", OFFSETOF(struct lock_order, the_bird));
+static struct domain_generic the_bird_domain_gen = DOMAIN_INIT(OFFSETOF(struct lock_order, the_bird));
DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen };
struct domain_generic *
-domain_new(const char *name, uint order)
+domain_new(uint order)
{
ASSERT_DIE(order < sizeof(struct lock_order));
struct domain_generic *dg = xmalloc(sizeof(struct domain_generic));
- *dg = (struct domain_generic) DOMAIN_INIT(name, order);
+ *dg = (struct domain_generic) DOMAIN_INIT(order);
return dg;
}
return dg->order;
}
+void
+domain_setup(struct domain_generic *dg, const char *name, pool *p)
+{
+ ASSERT_DIE(dg->pool == NULL);
+ dg->pool = p;
+ dg->name = name;
+}
+
void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
{
struct lock_order stack_copy;
void
cmd_show_threads(int show_loops)
{
- DOMAIN(control) lock = DOMAIN_NEW(control, "Show Threads");
+ DOMAIN(control) lock = DOMAIN_NEW(control);
LOCK_DOMAIN(control, lock);
pool *p = rp_new(&root_pool, lock.control, "Show Threads");
{
struct birdloop_pickup_group *group = &pickup_groups[i];
- group->domain = DOMAIN_NEW(resource, "Loop Pickup");
+ group->domain = DOMAIN_NEW(resource);
+ DOMAIN_SETUP(resource, group->domain, "Loop Pickup", NULL);
init_list(&group->loops);
init_list(&group->threads);
}
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);
+ struct domain_generic *dg = domain_new(order);
DG_LOCK(dg);
pool *p = rp_vnewf(pp, dg, name, args);
return 0;
}
+ struct domain_generic *sock_lock = DG_IS_LOCKED(s->pool->domain) ? NULL : s->pool->domain;
+ if (sock_lock)
+ DG_LOCK(sock_lock);
+
sock *t = sk_new(s->pool);
t->type = type;
t->data = s->data;
close(t->fd);
t->fd = -1;
sk_close(t);
- return 1;
+ t = NULL;
+ }
+ else
+ {
+ birdloop_add_socket(s->loop, t);
+ sk_alloc_bufs(t);
}
- birdloop_add_socket(s->loop, t);
+ if (sock_lock)
+ DG_UNLOCK(sock_lock);
+
+ if (t)
+ s->rx_hook(t, 0);
- sk_alloc_bufs(t);
- s->rx_hook(t, 0);
return 1;
}