THREADPOOL(9) | Kernel Developer's Manual | THREADPOOL(9) |
threadpool
—
#include <sys/threadpool.h>
typedef void threadpool_job_fn_t(struct threadpool_job *);
int
threadpool_get
(struct
threadpool **poolp, pri_t
pri);
void
threadpool_put
(struct
threadpool *pool, pri_t
pri);
int
threadpool_percpu_get
(struct
threadpool_percpu **pool_percpup,
pri_t pri);
void
threadpool_percpu_put
(struct
threadpool_percpu *pool_percpu,
pri_t pri);
struct threadpool *
threadpool_percpu_ref
(struct
threadpool_percpu *pool);
struct threadpool *
threadpool_percpu_ref_remote
(struct
threadpool_percpu *pool,
struct cpu_info *ci);
void
threadpool_job_init
(struct
threadpool_job *job,
threadpool_job_fn_t fn,
kmutex_t *interlock);
void
threadpool_job_destroy
(struct
threadpool_job *job);
void
threadpool_job_done
(struct
threadpool_job *job);
void
threadpool_schedule_job
(struct
threadpool *pool, struct
threadpool_job *job);
void
threadpool_cancel_job
(struct
threadpool *pool, struct
threadpool_job *job);
bool
threadpool_cancel_job_async
(struct
threadpool *pool, struct
threadpool_job *job);
threadpool
abstraction is provided to share a pool
of kthread(9) kernel threads
for medium- to long-term actions, called jobs, which can be scheduled from
contexts that do not allow sleeping.
For each priority level, there is one unbound thread pool, and one
collection of per-CPU thread pools. Access to the unbound thread pools is
provided by threadpool_get
() and
threadpool_put
(). Access to the per-CPU thread pools
is provided by threadpool_percpu_get
() and
threadpool_percpu_put
().
Job state is stored in the threadpool_job
structure. Callers of the threadpool
abstraction
must allocate memory for threadpool_job structures,
but should consider them opaque, and should not inspect or copy them. Each
job represented by a threadpool_job structure will be
run only once at a time, until the action associated with it calls
threadpool_job_done
().
Jobs are run in thread context and may take arbitrarily long to run or sleep arbitrarily long.
threadpool_get
(poolp,
pri)May sleep.
threadpool_put
(pool,
pri)threadpool_get
() to obtain
pool.
May sleep.
Do not use threadpool_put
() with
thread pools obtained from
threadpool_percpu_ref
() or
threadpool_percpu_ref_remote
().
threadpool_percpu_get
(pool_percpup,
pri)Use threadpool_percpu_ref
() or
threadpool_percpu_ref_remote
() with it to get at
the thread pool for a particular CPU.
May sleep.
threadpool_percpu_put
(pool_percpu,
pri)May sleep.
threadpool_percpu_ref
(pool_percpu)The resulting thread pool pointer is stable until
pool_percpu is released with
threadpool_percpu_put
(). Using it to schedule or
cancel a job does not require being on the same CPU.
Do not use threadpool_put
() with
thread pools obtained from
threadpool_percpu_ref
().
threadpool_percpu_ref_remote
(pool_percpu,
ci)The resulting thread pool pointer is stable until
pool_percpu is released with
threadpool_percpu_put
(). Using it to schedule or
cancel a job does not require being on the same CPU, but it is faster
and friendlier to the cache to use
threadpool_percpu_ref
() and use the resulting
thread pool only on the same CPU.
Do not use threadpool_put
() with
thread pools obtained from
threadpool_percpu_ref_remote
().
threadpool_job_init
(job,
fn, interlock)The mutex interlock is used to
synchronize job scheduling and completion. The action
fn is required to eventually call
threadpool_job_done
(), with
interlock held. This is so that while the job is
running and may be waiting for work to do, scheduling the job has no
effect, but as soon as the job is done, scheduling the job will cause it
to run again.
To change the action of a job, you must use
threadpool_job_destroy
() first and then call
threadpool_job_init
() again.
threadpool_job_destroy
(job)threadpool_cancel_job
() to cancel it. However,
threadpool_cancel_job_async
() is not enough.threadpool_job_done
(job)threadpool_schedule_job
() will cause it to re-run
its action.
threadpool_job_done
() must be called
exactly once by a job's action, and may not be called in any other
context.
threadpool_schedule_job
(pool,
job)Caller must hold the interlock of job.
threadpool_schedule_job
() may be
called in any context, including hard interrupt context, except at
interrupt priority levels above IPL_VM.
threadpool_cancel_job
(pool,
job)Caller must hold the interlock of job, which may be released in order to wait for completion.
If job has not been scheduled,
threadpool_cancel_job
() returns immediately. If
job has been scheduled, it must have been
scheduled in pool, not in any other thread
pool.
May sleep.
threadpool_cancel_job_async
(pool,
job)threadpool_cancel_job
(), but if it is already
running, return false instead of waiting; otherwise,
if it was not scheduled, or if it was scheduled and has not yet begun to
run, return true.
Caller must hold the interlock of job.
threadpool_cancel_job_async
() may be
called in any context, including hard interrupt context, except at
interrupt priority levels above IPL_VM.
threadpool
abstraction is implemented in
sys/kern/kern_threadpool.c.
December 26, 2018 | NetBSD 9.2 |