Module Name: src Committed By: thorpej Date: Wed Dec 26 21:15:50 UTC 2018
Modified Files: src/sys/kern: kern_threadpool.c Log Message: Simplify thread reference counting of the thread pool object. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/kern/kern_threadpool.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_threadpool.c diff -u src/sys/kern/kern_threadpool.c:1.6 src/sys/kern/kern_threadpool.c:1.7 --- src/sys/kern/kern_threadpool.c:1.6 Wed Dec 26 20:30:36 2018 +++ src/sys/kern/kern_threadpool.c Wed Dec 26 21:15:50 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_threadpool.c,v 1.6 2018/12/26 20:30:36 thorpej Exp $ */ +/* $NetBSD: kern_threadpool.c,v 1.7 2018/12/26 21:15:50 thorpej Exp $ */ /*- * Copyright (c) 2014, 2018 The NetBSD Foundation, Inc. @@ -81,7 +81,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.6 2018/12/26 20:30:36 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.7 2018/12/26 21:15:50 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -127,14 +127,14 @@ struct threadpool { struct threadpool_thread tp_overseer; struct job_head tp_jobs; struct thread_head tp_idle_threads; - unsigned int tp_refcnt; + uint64_t tp_refcnt; int tp_flags; #define THREADPOOL_DYING 0x01 struct cpu_info *tp_cpu; pri_t tp_pri; }; -static int threadpool_hold(struct threadpool *); +static void threadpool_hold(struct threadpool *); static void threadpool_rele(struct threadpool *); static int threadpool_percpu_create(struct threadpool_percpu **, pri_t); @@ -274,13 +274,11 @@ threadpool_create(struct threadpool *con /* XXX overseer */ TAILQ_INIT(&pool->tp_jobs); TAILQ_INIT(&pool->tp_idle_threads); - pool->tp_refcnt = 0; + pool->tp_refcnt = 1; /* overseer's reference */ pool->tp_flags = 0; pool->tp_cpu = ci; pool->tp_pri = pri; - error = threadpool_hold(pool); - KASSERT(error == 0); pool->tp_overseer.tpt_lwp = NULL; pool->tp_overseer.tpt_pool = pool; pool->tp_overseer.tpt_job = NULL; @@ -348,40 +346,24 @@ threadpool_destroy(struct threadpool *po mutex_destroy(&pool->tp_lock); } -static int +static void threadpool_hold(struct threadpool *pool) { - unsigned int refcnt; - - do { - refcnt = pool->tp_refcnt; - if (refcnt == UINT_MAX) - return EBUSY; - } while (atomic_cas_uint(&pool->tp_refcnt, refcnt, (refcnt + 1)) - != refcnt); - return 0; + KASSERT(mutex_owned(&pool->tp_lock)); + pool->tp_refcnt++; + KASSERT(pool->tp_refcnt != 0); } static void threadpool_rele(struct threadpool *pool) { - unsigned int refcnt; - do { - refcnt = pool->tp_refcnt; - KASSERT(0 < refcnt); - if (refcnt == 1) { - mutex_spin_enter(&pool->tp_lock); - refcnt = atomic_dec_uint_nv(&pool->tp_refcnt); - KASSERT(refcnt != UINT_MAX); - if (refcnt == 0) - cv_broadcast(&pool->tp_overseer.tpt_cv); - mutex_spin_exit(&pool->tp_lock); - return; - } - } while (atomic_cas_uint(&pool->tp_refcnt, refcnt, (refcnt - 1)) - != refcnt); + KASSERT(mutex_owned(&pool->tp_lock)); + KASSERT(0 < pool->tp_refcnt); + pool->tp_refcnt--; + if (pool->tp_refcnt == 0) + cv_broadcast(&pool->tp_overseer.tpt_cv); } /* Unbound thread pools */ @@ -876,12 +858,7 @@ threadpool_overseer_thread(void *arg) if (TAILQ_EMPTY(&pool->tp_idle_threads)) { TP_LOG(("%s: Got a job, need to create a thread.\n", __func__)); - error = threadpool_hold(pool); - if (error) { - (void)kpause("thrdplrf", false, hz, - &pool->tp_lock); - continue; - } + threadpool_hold(pool); mutex_spin_exit(&pool->tp_lock); struct threadpool_thread *const thread = @@ -910,6 +887,10 @@ threadpool_overseer_thread(void *arg) &pool->tp_lock); continue; } + /* + * New kthread now owns the reference to the pool + * taken above. + */ KASSERT(lwp != NULL); TAILQ_INSERT_TAIL(&pool->tp_idle_threads, thread, tpt_entry); @@ -972,11 +953,11 @@ threadpool_overseer_thread(void *arg) mutex_spin_enter(&pool->tp_lock); } + threadpool_rele(pool); mutex_spin_exit(&pool->tp_lock); TP_LOG(("%s: exiting.\n", __func__)); - threadpool_rele(pool); kthread_exit(0); } @@ -1045,6 +1026,7 @@ threadpool_thread(void *arg) thread->tpt_job = NULL; TAILQ_INSERT_TAIL(&pool->tp_idle_threads, thread, tpt_entry); } + threadpool_rele(pool); mutex_spin_exit(&pool->tp_lock); TP_LOG(("%s: thread %p exiting.\n", __func__, thread)); @@ -1052,6 +1034,5 @@ threadpool_thread(void *arg) KASSERT(!cv_has_waiters(&thread->tpt_cv)); cv_destroy(&thread->tpt_cv); pool_cache_put(threadpool_thread_pc, thread); - threadpool_rele(pool); kthread_exit(0); }