/* Get birdloop's pool */
pool *birdloop_pool(struct birdloop *loop);
-/* Enter and exit the birdloop */
+/* Enter the birdloop, leave at the end of the block. */
+#define BIRDLOOP_ENTER(_loop) CLEANUP(birdloop_leave_cleanup) UNUSED struct birdloop *_loop_entered = (birdloop_enter(_loop), (_loop))
+
+/* Auxiliary cleanup function for BIRDLOOP_ENTER */
+void birdloop_leave_cleanup(struct birdloop **);
+
+/* Explicitly enter and exit the birdloop */
void birdloop_enter(struct birdloop *loop);
void birdloop_leave(struct birdloop *loop);
+/* Check whether we are actually inside a birdloop */
bool birdloop_inside(struct birdloop *loop);
+/* Internal API, do not call */
void birdloop_mask_wakeups(struct birdloop *loop);
void birdloop_unmask_wakeups(struct birdloop *loop);
int lock_dst = 0;
- birdloop_enter(dst_pub->loop);
+ BIRDLOOP_ENTER(dst_pub->loop);
RT_LOCKED(src_pub, src)
{
if (lock_dst)
rt_lock_table(dst_pub);
-
- birdloop_leave(dst_pub->loop);
}
void
rt_flowspec_unlink(rtable *src, rtable *dst)
{
- birdloop_enter(dst->loop);
+ BIRDLOOP_ENTER(dst->loop);
bool unlock_dst = 0;
if (unlock_dst)
rt_unlock_table(dst);
-
- birdloop_leave(dst->loop);
}
static void
/* Start the service thread */
struct birdloop *loop = birdloop_new(pp, DOMAIN_ORDER(service), cf->thread_group->group, "Routing table service %s", cf->name);
- birdloop_enter(loop);
+ BIRDLOOP_ENTER(loop);
pool *sp = birdloop_pool(loop);
/* Create the table domain and pool */
CALL(cf->master.setup, RT_PUB(t));
- birdloop_leave(t->loop);
-
return RT_PUB(t);
}
WALK_LIST(o, old->tables)
{
bool ok;
- birdloop_enter(o->table->loop);
- RT_LOCKED(o->table, tab)
{
- r = OBSREF_GET(tab->deleted) ? NULL : rt_find_table_config(new, o->name);
- ok = r && !new->shutdown && rt_reconfigure(tab, r, o);
+ BIRDLOOP_ENTER(o->table->loop);
+ RT_LOCKED(o->table, tab)
+ {
+ r = OBSREF_GET(tab->deleted) ? NULL : rt_find_table_config(new, o->name);
+ ok = r && !new->shutdown && rt_reconfigure(tab, r, o);
+ }
}
- birdloop_leave(o->table->loop);
if (ok)
continue;
- birdloop_enter(o->table->loop);
+ BIRDLOOP_ENTER(o->table->loop);
RT_LOCKED(o->table, tab)
{
DBG("\t%s: deleted\n", o->name);
}
CALL(o->table->config->master.stop, o->table);
- birdloop_leave(o->table->loop);
}
}
uint dropped = 0;
WALK_TLIST_DELSAFE(birdloop, loop, &this_thread->loops)
{
- birdloop_enter(loop);
+ BIRDLOOP_ENTER(loop);
if (ev_active(&loop->event) && !loop->stopped && !birdloop_hot_potato(loop))
{
/* Pass to another thread */
break;
}
}
- birdloop_leave(loop);
}
if (dropped)
WALK_TLIST(birdloop, loop, &thr->loops)
{
- birdloop_enter(loop);
+ BIRDLOOP_ENTER(loop);
sockets_prepare(loop, &pfd);
- birdloop_leave(loop);
}
ASSERT_DIE(pfd.loop.used == pfd.pfd.used);
while (!EMPTY_TLIST(birdloop, leftover_loops))
{
struct birdloop *loop = THEAD(birdloop, leftover_loops);
- birdloop_enter(loop);
+ BIRDLOOP_ENTER(loop);
if (loop->thread_group == gpub)
{
birdloop_transfer(loop, gpub, default_thread_group);
birdloop_rem_node(leftover_loops, loop);
birdloop_set_thread(loop, NULL);
- birdloop_leave(loop);
}
thread_group_rem_node(&global_thread_group_list, gpub);
bird_thread_stop(thread_group *gpub, struct config *old_config)
{
struct birdloop *tdl = birdloop_new(&root_pool, DOMAIN_ORDER(control), gpub, "Thread dropper");
- birdloop_enter(tdl);
+ BIRDLOOP_ENTER(tdl);
TG_LOCKED(gpub, group)
{
OBSREF_SET(group->thread_dropper.conflock, old_config);
ev_send_loop(tdl, &group->thread_dropper.event);
}
-
- birdloop_leave(tdl);
}
void
DG_UNLOCK(loop->time.domain);
}
+void
+birdloop_leave_cleanup(struct birdloop **loop)
+{
+ if (*loop)
+ birdloop_leave(*loop);
+}
+
void
birdloop_mask_wakeups(struct birdloop *loop)
{