From c17843a200ffd70903d3f7170883d671bafc80af Mon Sep 17 00:00:00 2001 From: Jan Vcelak <jan.vcelak@nic.cz> Date: Fri, 12 Sep 2014 13:33:15 +0200 Subject: [PATCH] suspend background workers during reload refs #296 --- src/knot/server/server.c | 8 +++++--- src/knot/worker/pool.c | 30 +++++++++++++++++++++++++++++- src/knot/worker/pool.h | 10 ++++++++++ src/knot/zone/events.c | 2 +- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/knot/server/server.c b/src/knot/server/server.c index d36ddd57a..a165b5a77 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -588,12 +588,13 @@ int server_update_zones(const struct conf_t *conf, void *data) { server_t *server = (server_t *)data; - /* Prevent new events on zones waiting to be replaced. */ + /* Prevent emitting of new zone events. */ if (server->zone_db) { knot_zonedb_foreach(server->zone_db, zone_events_freeze); } - /* Finish operations already in the queue. */ + /* Suspend workers, clear wating events, finish running events. */ + worker_pool_suspend(server->workers); worker_pool_clear(server->workers); worker_pool_wait(server->workers); @@ -603,7 +604,8 @@ int server_update_zones(const struct conf_t *conf, void *data) /* Trim extra heap. */ mem_trim(); - /* Plan events on new zones. */ + /* Resume workers and allow events on new zones. */ + worker_pool_resume(server->workers); if (server->zone_db) { knot_zonedb_foreach(server->zone_db, zone_events_start); } diff --git a/src/knot/worker/pool.c b/src/knot/worker/pool.c index aede4e9aa..ac71deadf 100644 --- a/src/knot/worker/pool.c +++ b/src/knot/worker/pool.c @@ -35,6 +35,7 @@ struct worker_pool { pthread_cond_t wake; bool terminating; /*!< Is the pool terminating? .*/ + bool suspended; /*!< Is execution temporarily suspended? .*/ int running; /*!< Number of running threads. */ worker_queue_t tasks; }; @@ -61,7 +62,11 @@ static int worker_main(dthread_t *thread) break; } - task_t *task = worker_queue_dequeue(&pool->tasks); + task_t *task = NULL; + if (!pool->suspended) { + task = worker_queue_dequeue(&pool->tasks); + } + if (task == NULL) { pthread_cond_wait(&pool->wake, &pool->lock); continue; @@ -162,6 +167,29 @@ void worker_pool_stop(worker_pool_t *pool) dt_stop(pool->threads); } +void worker_pool_suspend(worker_pool_t *pool) +{ + if (!pool) { + return; + } + + pthread_mutex_lock(&pool->lock); + pool->suspended = true; + pthread_mutex_unlock(&pool->lock); +} + +void worker_pool_resume(worker_pool_t *pool) +{ + if (!pool) { + return; + } + + pthread_mutex_lock(&pool->lock); + pool->suspended = false; + pthread_cond_broadcast(&pool->wake); + pthread_mutex_unlock(&pool->lock); +} + void worker_pool_join(worker_pool_t *pool) { if (!pool) { diff --git a/src/knot/worker/pool.h b/src/knot/worker/pool.h index fcaae2880..424b5b11c 100644 --- a/src/knot/worker/pool.h +++ b/src/knot/worker/pool.h @@ -45,6 +45,16 @@ void worker_pool_start(worker_pool_t *pool); */ void worker_pool_stop(worker_pool_t *pool); +/*! + * \brief Temporarily suspend the execution of worker pool. + */ +void worker_pool_suspend(worker_pool_t *pool); + +/*! + * \brief Resume the execution of worker pool. + */ +void worker_pool_resume(worker_pool_t *pool); + /*! * \brief Wait for all threads to terminate. */ diff --git a/src/knot/zone/events.c b/src/knot/zone/events.c index 1235dad54..0252eeb77 100644 --- a/src/knot/zone/events.c +++ b/src/knot/zone/events.c @@ -921,7 +921,7 @@ void zone_events_enqueue(zone_t *zone, zone_event_type_t type) pthread_mutex_lock(&events->mx); - /* Possible only if no event is running at the moment. */ + /* Bypass scheduler if no event is running. */ if (!events->running && !events->frozen) { events->running = true; event_set_time(events, type, ZONE_EVENT_IMMEDIATE); -- GitLab