Previous protection scheme of wi->nr_thread in work.c was unclear because wi->startup_lock was also used for protecting it during workqueue grow/shrink. This patch let work.c protect wi->nr_thread by the new wi->workers_lock.
Signed-off-by: Hitoshi Mitake <[email protected]> --- lib/work.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/work.c b/lib/work.c index 50b57a5..9d5c5a9 100644 --- a/lib/work.c +++ b/lib/work.c @@ -55,6 +55,9 @@ struct worker_info { pthread_mutex_t pending_lock; /* protected by pending_lock */ struct work_queue q; + + pthread_mutex_t workers_lock; + /* protected by workers_lock */ size_t nr_threads; /* protected by uatomic primitives */ @@ -247,18 +250,18 @@ static int create_worker_threads(struct worker_info *wi, size_t nr_threads) pthread_t thread; int ret; - pthread_mutex_lock(&wi->startup_lock); + pthread_mutex_lock(&wi->workers_lock); while (wi->nr_threads < nr_threads) { ret = pthread_create(&thread, NULL, worker_routine, wi); if (ret != 0) { sd_err("failed to create worker thread: %m"); - pthread_mutex_unlock(&wi->startup_lock); + pthread_mutex_unlock(&wi->workers_lock); return -1; } wi->nr_threads++; sd_debug("create thread %s %zu", wi->name, wi->nr_threads); } - pthread_mutex_unlock(&wi->startup_lock); + pthread_mutex_unlock(&wi->workers_lock); return 0; } @@ -323,10 +326,13 @@ static void *worker_routine(void *arg) pthread_mutex_lock(&wi->pending_lock); if (wq_need_shrink(wi)) { + pthread_mutex_unlock(&wi->pending_lock); + + pthread_mutex_lock(&wi->workers_lock); wi->nr_threads--; + pthread_mutex_unlock(&wi->workers_lock); trace_clear_tid_map(tid); - pthread_mutex_unlock(&wi->pending_lock); pthread_detach(pthread_self()); sd_debug("destroy thread %s %d, %zu", wi->name, tid, wi->nr_threads); @@ -415,6 +421,7 @@ struct work_queue *create_work_queue(const char *name, pthread_mutex_init(&wi->finished_lock, NULL); pthread_mutex_init(&wi->pending_lock, NULL); pthread_mutex_init(&wi->startup_lock, NULL); + pthread_mutex_init(&wi->workers_lock, NULL); ret = create_worker_threads(wi, 1); if (ret < 0) @@ -424,6 +431,7 @@ struct work_queue *create_work_queue(const char *name, return &wi->q; destroy_threads: + pthread_mutex_unlock(&wi->workers_lock); pthread_mutex_unlock(&wi->startup_lock); pthread_cond_destroy(&wi->pending_cond); pthread_mutex_destroy(&wi->pending_lock); -- 1.7.10.4 -- sheepdog mailing list [email protected] http://lists.wpkg.org/mailman/listinfo/sheepdog
