From 7776e47e321e0561a0ae8934a2d1f6414bce9002 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 21 Aug 2023 15:37:09 +0200 Subject: [PATCH] Config obstacles are lockless now --- conf/conf.c | 19 ++++++++++--------- conf/conf.h | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/conf/conf.c b/conf/conf.c index c7cd81fe..99927ce0 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -70,7 +70,7 @@ static int future_cftype; /* Type of scheduled transition, may also be RECONFIG /* 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 */ @@ -110,6 +110,8 @@ config_alloc(const char *name) 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; } @@ -228,16 +230,15 @@ void 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 @@ -313,8 +314,11 @@ config_do_commit(struct config *c, int type) } static void -config_done(void *unused UNUSED) +config_done(void *cf) { + if (cf == config) + return; + if (config->shutdown) sysdep_shutdown_done(); @@ -517,9 +521,6 @@ config_init(void) { 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; } diff --git a/conf/conf.h b/conf/conf.h index b30914c1..c51b01c9 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -57,7 +57,8 @@ struct config { 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 */