Module Name: src
Committed By: riastradh
Date: Wed Jan 13 02:20:15 UTC 2021
Modified Files:
src/sys/kern: kern_threadpool.c
Log Message:
threadpool(9): Tidy up thread naming.
- `dispatcher', not `overseer' -- much more appropriate metaphor.
- Just omit `/-1' from unbound thread names.
- Just omit `@-1' from dynamic-priority (PRI_NONE) thread names.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 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.20 src/sys/kern/kern_threadpool.c:1.21
--- src/sys/kern/kern_threadpool.c:1.20 Wed Jan 13 02:19:08 2021
+++ src/sys/kern/kern_threadpool.c Wed Jan 13 02:20:15 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_threadpool.c,v 1.20 2021/01/13 02:19:08 riastradh Exp $ */
+/* $NetBSD: kern_threadpool.c,v 1.21 2021/01/13 02:20:15 riastradh Exp $ */
/*-
* Copyright (c) 2014, 2018 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
* Thread pools.
*
* A thread pool is a collection of worker threads idle or running
- * jobs, together with an overseer thread that does not run jobs but
+ * jobs, together with an dispatcher thread that does not run jobs but
* can be given jobs to assign to a worker thread. Scheduling a job in
* a thread pool does not allocate or even sleep at all, except perhaps
* on an adaptive lock, unlike kthread_create. Jobs reuse threads, so
@@ -56,32 +56,32 @@
* CPU. When you're done, call threadpool_percpu_put(pool_percpu,
* pri).
*
- * +--MACHINE-----------------------------------------------+
- * | +--CPU 0-------+ +--CPU 1-------+ +--CPU n-------+ |
- * | | <overseer 0> | | <overseer 1> | ... | <overseer n> | |
- * | | <idle 0a> | | <running 1a> | ... | <idle na> | |
- * | | <running 0b> | | <running 1b> | ... | <idle nb> | |
- * | | . | | . | ... | . | |
- * | | . | | . | ... | . | |
- * | | . | | . | ... | . | |
- * | +--------------+ +--------------+ +--------------+ |
- * | +--unbound---------+ |
- * | | <overseer n+1> | |
- * | | <idle (n+1)a> | |
- * | | <running (n+1)b> | |
- * | +------------------+ |
- * +--------------------------------------------------------+
+ * +--MACHINE-----------------------------------------------------+
+ * | +--CPU 0---------+ +--CPU 1---------+ +--CPU n---------+ |
+ * | | <dispatcher 0> | | <dispatcher 1> | ... | <dispatcher n> | |
+ * | | <idle 0a> | | <running 1a> | ... | <idle na> | |
+ * | | <running 0b> | | <running 1b> | ... | <idle nb> | |
+ * | | . | | . | ... | . | |
+ * | | . | | . | ... | . | |
+ * | | . | | . | ... | . | |
+ * | +----------------+ +----------------+ +----------------+ |
+ * | +--unbound-----------+ |
+ * | | <dispatcher n+1> | |
+ * | | <idle (n+1)a> | |
+ * | | <running (n+1)b> | |
+ * | +--------------------+ |
+ * +--------------------------------------------------------------+
*
- * XXX Why one overseer per CPU? I did that originally to avoid
+ * XXX Why one dispatcher per CPU? I did that originally to avoid
* touching remote CPUs' memory when scheduling a job, but that still
* requires interprocessor synchronization. Perhaps we could get by
- * with a single overseer thread, at the expense of another pointer in
- * struct threadpool_job to identify the CPU on which it must run
- * in order for the overseer to schedule it correctly.
+ * with a single dispatcher thread, at the expense of another pointer
+ * in struct threadpool_job to identify the CPU on which it must run in
+ * order for the dispatcher to schedule it correctly.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.20 2021/01/13 02:19:08 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.21 2021/01/13 02:20:15 riastradh Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -141,27 +141,27 @@ SDT_PROBE_DEFINE2(sdt, kernel, threadpoo
"struct threadpool *"/*pool*/, "struct threadpool_job *"/*job*/);
SDT_PROBE_DEFINE2(sdt, kernel, threadpool, schedule__job__running,
"struct threadpool *"/*pool*/, "struct threadpool_job *"/*job*/);
-SDT_PROBE_DEFINE2(sdt, kernel, threadpool, schedule__job__overseer,
+SDT_PROBE_DEFINE2(sdt, kernel, threadpool, schedule__job__dispatcher,
"struct threadpool *"/*pool*/, "struct threadpool_job *"/*job*/);
SDT_PROBE_DEFINE3(sdt, kernel, threadpool, schedule__job__thread,
"struct threadpool *"/*pool*/,
"struct threadpool_job *"/*job*/,
"struct lwp *"/*thread*/);
-SDT_PROBE_DEFINE1(sdt, kernel, threadpool, overseer__start,
+SDT_PROBE_DEFINE1(sdt, kernel, threadpool, dispatcher__start,
"struct threadpool *"/*pool*/);
-SDT_PROBE_DEFINE1(sdt, kernel, threadpool, overseer__dying,
+SDT_PROBE_DEFINE1(sdt, kernel, threadpool, dispatcher__dying,
"struct threadpool *"/*pool*/);
-SDT_PROBE_DEFINE1(sdt, kernel, threadpool, overseer__spawn,
+SDT_PROBE_DEFINE1(sdt, kernel, threadpool, dispatcher__spawn,
"struct threadpool *"/*pool*/);
-SDT_PROBE_DEFINE2(sdt, kernel, threadpool, overseer__race,
+SDT_PROBE_DEFINE2(sdt, kernel, threadpool, dispatcher__race,
"struct threadpool *"/*pool*/,
"struct threadpool_job *"/*job*/);
-SDT_PROBE_DEFINE3(sdt, kernel, threadpool, overseer__assign,
+SDT_PROBE_DEFINE3(sdt, kernel, threadpool, dispatcher__assign,
"struct threadpool *"/*pool*/,
"struct threadpool_job *"/*job*/,
"struct lwp *"/*thread*/);
-SDT_PROBE_DEFINE1(sdt, kernel, threadpool, overseer__exit,
+SDT_PROBE_DEFINE1(sdt, kernel, threadpool, dispatcher__exit,
"struct threadpool *"/*pool*/);
SDT_PROBE_DEFINE1(sdt, kernel, threadpool, thread__start,
@@ -189,7 +189,7 @@ struct threadpool_thread {
struct threadpool {
kmutex_t tp_lock;
- struct threadpool_thread tp_overseer;
+ struct threadpool_thread tp_dispatcher;
struct job_head tp_jobs;
struct thread_head tp_idle_threads;
uint64_t tp_refcnt;
@@ -213,7 +213,7 @@ static threadpool_job_fn_t threadpool_jo
static void threadpool_job_hold(struct threadpool_job *);
static void threadpool_job_rele(struct threadpool_job *);
-static void threadpool_overseer_thread(void *) __dead;
+static void threadpool_dispatcher_thread(void *) __dead;
static void threadpool_thread(void *) __dead;
static pool_cache_t threadpool_thread_pc __read_mostly;
@@ -356,6 +356,18 @@ threadpools_init(void)
mutex_init(&threadpools_lock, MUTEX_DEFAULT, IPL_NONE);
}
+static void
+threadnamesuffix(char *buf, size_t buflen, struct cpu_info *ci, int pri)
+{
+
+ buf[0] = '\0';
+ if (ci)
+ snprintf(buf + strlen(buf), buflen - strlen(buf), "/%d",
+ cpu_index(ci));
+ if (pri != PRI_NONE)
+ snprintf(buf + strlen(buf), buflen - strlen(buf), "@%d", pri);
+}
+
/* Thread pool creation */
static bool
@@ -369,6 +381,7 @@ threadpool_create(struct threadpool *con
pri_t pri)
{
struct lwp *lwp;
+ char suffix[16];
int ktflags;
int error;
@@ -377,46 +390,46 @@ threadpool_create(struct threadpool *con
SDT_PROBE2(sdt, kernel, threadpool, create, ci, pri);
mutex_init(&pool->tp_lock, MUTEX_DEFAULT, IPL_VM);
- /* XXX overseer */
+ /* XXX dispatcher */
TAILQ_INIT(&pool->tp_jobs);
TAILQ_INIT(&pool->tp_idle_threads);
- pool->tp_refcnt = 1; /* overseer's reference */
+ pool->tp_refcnt = 1; /* dispatcher's reference */
pool->tp_flags = 0;
pool->tp_cpu = ci;
pool->tp_pri = pri;
- pool->tp_overseer.tpt_lwp = NULL;
- pool->tp_overseer.tpt_pool = pool;
- pool->tp_overseer.tpt_job = NULL;
- cv_init(&pool->tp_overseer.tpt_cv, "poolover");
+ pool->tp_dispatcher.tpt_lwp = NULL;
+ pool->tp_dispatcher.tpt_pool = pool;
+ pool->tp_dispatcher.tpt_job = NULL;
+ cv_init(&pool->tp_dispatcher.tpt_cv, "pooldisp");
ktflags = 0;
ktflags |= KTHREAD_MPSAFE;
if (pri < PRI_KERNEL)
ktflags |= KTHREAD_TS;
- error = kthread_create(pri, ktflags, ci, &threadpool_overseer_thread,
- &pool->tp_overseer, &lwp,
- "pooloverseer/%d@%d", (ci ? cpu_index(ci) : -1), (int)pri);
+ threadnamesuffix(suffix, sizeof(suffix), ci, pri);
+ error = kthread_create(pri, ktflags, ci, &threadpool_dispatcher_thread,
+ &pool->tp_dispatcher, &lwp, "pooldisp%s", suffix);
if (error)
goto fail0;
mutex_spin_enter(&pool->tp_lock);
- pool->tp_overseer.tpt_lwp = lwp;
- cv_broadcast(&pool->tp_overseer.tpt_cv);
+ pool->tp_dispatcher.tpt_lwp = lwp;
+ cv_broadcast(&pool->tp_dispatcher.tpt_cv);
mutex_spin_exit(&pool->tp_lock);
SDT_PROBE3(sdt, kernel, threadpool, create__success, ci, pri, pool);
return 0;
fail0: KASSERT(error);
- KASSERT(pool->tp_overseer.tpt_job == NULL);
- KASSERT(pool->tp_overseer.tpt_pool == pool);
+ KASSERT(pool->tp_dispatcher.tpt_job == NULL);
+ KASSERT(pool->tp_dispatcher.tpt_pool == pool);
KASSERT(pool->tp_flags == 0);
KASSERT(pool->tp_refcnt == 0);
KASSERT(TAILQ_EMPTY(&pool->tp_idle_threads));
KASSERT(TAILQ_EMPTY(&pool->tp_jobs));
- KASSERT(!cv_has_waiters(&pool->tp_overseer.tpt_cv));
- cv_destroy(&pool->tp_overseer.tpt_cv);
+ KASSERT(!cv_has_waiters(&pool->tp_dispatcher.tpt_cv));
+ cv_destroy(&pool->tp_dispatcher.tpt_cv);
mutex_destroy(&pool->tp_lock);
SDT_PROBE3(sdt, kernel, threadpool, create__failure, ci, pri, error);
return error;
@@ -435,24 +448,24 @@ threadpool_destroy(struct threadpool *po
mutex_spin_enter(&pool->tp_lock);
KASSERT(TAILQ_EMPTY(&pool->tp_jobs));
pool->tp_flags |= THREADPOOL_DYING;
- cv_broadcast(&pool->tp_overseer.tpt_cv);
+ cv_broadcast(&pool->tp_dispatcher.tpt_cv);
TAILQ_FOREACH(thread, &pool->tp_idle_threads, tpt_entry)
cv_broadcast(&thread->tpt_cv);
while (0 < pool->tp_refcnt) {
SDT_PROBE2(sdt, kernel, threadpool, destroy__wait,
pool, pool->tp_refcnt);
- cv_wait(&pool->tp_overseer.tpt_cv, &pool->tp_lock);
+ cv_wait(&pool->tp_dispatcher.tpt_cv, &pool->tp_lock);
}
mutex_spin_exit(&pool->tp_lock);
- KASSERT(pool->tp_overseer.tpt_job == NULL);
- KASSERT(pool->tp_overseer.tpt_pool == pool);
+ KASSERT(pool->tp_dispatcher.tpt_job == NULL);
+ KASSERT(pool->tp_dispatcher.tpt_pool == pool);
KASSERT(pool->tp_flags == THREADPOOL_DYING);
KASSERT(pool->tp_refcnt == 0);
KASSERT(TAILQ_EMPTY(&pool->tp_idle_threads));
KASSERT(TAILQ_EMPTY(&pool->tp_jobs));
- KASSERT(!cv_has_waiters(&pool->tp_overseer.tpt_cv));
- cv_destroy(&pool->tp_overseer.tpt_cv);
+ KASSERT(!cv_has_waiters(&pool->tp_dispatcher.tpt_cv));
+ cv_destroy(&pool->tp_dispatcher.tpt_cv);
mutex_destroy(&pool->tp_lock);
}
@@ -472,7 +485,7 @@ threadpool_rele(struct threadpool *pool)
KASSERT(mutex_owned(&pool->tp_lock));
KASSERT(0 < pool->tp_refcnt);
if (--pool->tp_refcnt == 0)
- cv_broadcast(&pool->tp_overseer.tpt_cv);
+ cv_broadcast(&pool->tp_dispatcher.tpt_cv);
}
/* Unbound thread pools */
@@ -859,10 +872,10 @@ threadpool_schedule_job(struct threadpoo
/* Otherwise, try to assign a thread to the job. */
mutex_spin_enter(&pool->tp_lock);
if (__predict_false(TAILQ_EMPTY(&pool->tp_idle_threads))) {
- /* Nobody's idle. Give it to the overseer. */
- SDT_PROBE2(sdt, kernel, threadpool, schedule__job__overseer,
+ /* Nobody's idle. Give it to the dispatcher. */
+ SDT_PROBE2(sdt, kernel, threadpool, schedule__job__dispatcher,
pool, job);
- job->job_thread = &pool->tp_overseer;
+ job->job_thread = &pool->tp_dispatcher;
TAILQ_INSERT_TAIL(&pool->tp_jobs, job, job_entry);
} else {
/* Assign it to the first idle thread. */
@@ -874,7 +887,7 @@ threadpool_schedule_job(struct threadpoo
job->job_thread->tpt_job = job;
}
- /* Notify whomever we gave it to, overseer or idle thread. */
+ /* Notify whomever we gave it to, dispatcher or idle thread. */
KASSERT(job->job_thread != NULL);
cv_broadcast(&job->job_thread->tpt_cv);
mutex_spin_exit(&pool->tp_lock);
@@ -898,19 +911,19 @@ threadpool_cancel_job_async(struct threa
* "luck of the draw").
*
* => "job" is not yet running, but is assigned to the
- * overseer.
+ * dispatcher.
*
* When this happens, this code makes the determination that
* the job is already running. The failure mode is that the
* caller is told the job is running, and thus has to wait.
- * The overseer will eventually get to it and the job will
+ * The dispatcher will eventually get to it and the job will
* proceed as if it had been already running.
*/
if (job->job_thread == NULL) {
/* Nothing to do. Guaranteed not running. */
return true;
- } else if (job->job_thread == &pool->tp_overseer) {
+ } else if (job->job_thread == &pool->tp_dispatcher) {
/* Take it off the list to guarantee it won't run. */
job->job_thread = NULL;
mutex_spin_enter(&pool->tp_lock);
@@ -945,15 +958,16 @@ threadpool_cancel_job(struct threadpool
cv_wait(&job->job_cv, job->job_lock);
}
-/* Thread pool overseer thread */
+/* Thread pool dispatcher thread */
static void __dead
-threadpool_overseer_thread(void *arg)
+threadpool_dispatcher_thread(void *arg)
{
- struct threadpool_thread *const overseer = arg;
- struct threadpool *const pool = overseer->tpt_pool;
+ struct threadpool_thread *const dispatcher = arg;
+ struct threadpool *const pool = dispatcher->tpt_pool;
struct lwp *lwp = NULL;
int ktflags;
+ char suffix[16];
int error;
KASSERT((pool->tp_cpu == NULL) || (pool->tp_cpu == curcpu()));
@@ -961,27 +975,27 @@ threadpool_overseer_thread(void *arg)
/* Wait until we're initialized. */
mutex_spin_enter(&pool->tp_lock);
- while (overseer->tpt_lwp == NULL)
- cv_wait(&overseer->tpt_cv, &pool->tp_lock);
+ while (dispatcher->tpt_lwp == NULL)
+ cv_wait(&dispatcher->tpt_cv, &pool->tp_lock);
- SDT_PROBE1(sdt, kernel, threadpool, overseer__start, pool);
+ SDT_PROBE1(sdt, kernel, threadpool, dispatcher__start, pool);
for (;;) {
/* Wait until there's a job. */
while (TAILQ_EMPTY(&pool->tp_jobs)) {
if (ISSET(pool->tp_flags, THREADPOOL_DYING)) {
SDT_PROBE1(sdt, kernel, threadpool,
- overseer__dying, pool);
+ dispatcher__dying, pool);
break;
}
- cv_wait(&overseer->tpt_cv, &pool->tp_lock);
+ cv_wait(&dispatcher->tpt_cv, &pool->tp_lock);
}
if (__predict_false(TAILQ_EMPTY(&pool->tp_jobs)))
break;
/* If there are no threads, we'll have to try to start one. */
if (TAILQ_EMPTY(&pool->tp_idle_threads)) {
- SDT_PROBE1(sdt, kernel, threadpool, overseer__spawn,
+ SDT_PROBE1(sdt, kernel, threadpool, dispatcher__spawn,
pool);
threadpool_hold(pool);
mutex_spin_exit(&pool->tp_lock);
@@ -991,17 +1005,17 @@ threadpool_overseer_thread(void *arg)
thread->tpt_lwp = NULL;
thread->tpt_pool = pool;
thread->tpt_job = NULL;
- cv_init(&thread->tpt_cv, "poolthrd");
+ cv_init(&thread->tpt_cv, "pooljob");
ktflags = 0;
ktflags |= KTHREAD_MPSAFE;
if (pool->tp_pri < PRI_KERNEL)
ktflags |= KTHREAD_TS;
+ threadnamesuffix(suffix, sizeof(suffix), pool->tp_cpu,
+ pool->tp_pri);
error = kthread_create(pool->tp_pri, ktflags,
pool->tp_cpu, &threadpool_thread, thread, &lwp,
- "poolthread/%d@%d",
- (pool->tp_cpu ? cpu_index(pool->tp_cpu) : -1),
- (int)pool->tp_pri);
+ "poolthread%s", suffix);
mutex_spin_enter(&pool->tp_lock);
if (error) {
@@ -1037,7 +1051,7 @@ threadpool_overseer_thread(void *arg)
mutex_enter(job->job_lock);
/* If the job was cancelled, we'll no longer be its thread. */
- if (__predict_true(job->job_thread == overseer)) {
+ if (__predict_true(job->job_thread == dispatcher)) {
mutex_spin_enter(&pool->tp_lock);
if (__predict_false(
TAILQ_EMPTY(&pool->tp_idle_threads))) {
@@ -1046,7 +1060,7 @@ threadpool_overseer_thread(void *arg)
* first. We'll have to try again.
*/
SDT_PROBE2(sdt, kernel, threadpool,
- overseer__race, pool, job);
+ dispatcher__race, pool, job);
TAILQ_INSERT_HEAD(&pool->tp_jobs, job,
job_entry);
} else {
@@ -1058,7 +1072,7 @@ threadpool_overseer_thread(void *arg)
TAILQ_FIRST(&pool->tp_idle_threads);
SDT_PROBE2(sdt, kernel, threadpool,
- overseer__assign, job, thread->tpt_lwp);
+ dispatcher__assign, job, thread->tpt_lwp);
KASSERT(thread->tpt_job == NULL);
TAILQ_REMOVE(&pool->tp_idle_threads, thread,
tpt_entry);
@@ -1076,7 +1090,7 @@ threadpool_overseer_thread(void *arg)
threadpool_rele(pool);
mutex_spin_exit(&pool->tp_lock);
- SDT_PROBE1(sdt, kernel, threadpool, overseer__exit, pool);
+ SDT_PROBE1(sdt, kernel, threadpool, dispatcher__exit, pool);
kthread_exit(0);
}