/* Note that when future_cftype is RECONFIG_UNDO, then future_config is NULL,
therefore proper check for future scheduled config checks future_cftype */
-static event *config_event; /* Event for finalizing reconfiguration */
+static void config_done(void *cf);
static timer *config_timer; /* Timer for scheduled configuration rollback */
/* These are public just for cmd_show_status(), should not be accessed elsewhere */
c->tf_base = c->tf_log = TM_ISO_LONG_MS;
c->gr_wait = DEFAULT_GR_WAIT;
+ c->done_event = (event) { .hook = config_done, .data = c, };
+
return c;
}
config_add_obstacle(struct config *c)
{
DBG("+++ adding obstacle %d\n", c->obstacle_count);
- c->obstacle_count++;
+ atomic_fetch_add_explicit(&c->obstacle_count, 1, memory_order_acq_rel);
}
void
config_del_obstacle(struct config *c)
{
DBG("+++ deleting obstacle %d\n", c->obstacle_count);
- c->obstacle_count--;
- if (!c->obstacle_count && (c != config))
- ev_schedule(config_event);
+ if (atomic_fetch_sub_explicit(&c->obstacle_count, 1, memory_order_acq_rel) == 1)
+ ev_send_loop(&main_birdloop, &c->done_event);
}
static int
}
static void
-config_done(void *unused UNUSED)
+config_done(void *cf)
{
+ if (cf == config)
+ return;
+
if (config->shutdown)
sysdep_shutdown_done();
{
config_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Configurations");
- config_event = ev_new(config_pool);
- config_event->hook = config_done;
-
config_timer = tm_new(config_pool);
config_timer->hook = config_timeout;
}
int thread_count; /* How many worker threads to prefork */
struct sym_scope *root_scope; /* Scope for root symbols */
- int obstacle_count; /* Number of items blocking freeing of this config */
+ _Atomic int obstacle_count; /* Number of items blocking freeing of this config */
+ event done_event; /* Called when obstacle_count reaches zero */
int shutdown; /* This is a pseudo-config for daemon shutdown */
int gr_down; /* This is a pseudo-config for graceful restart */
btime load_time; /* When we've got this configuration */