Date: Sat, 24 May 2014 20:37:15 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266629 - in head/sys: kern sys Message-ID: <201405242037.s4OKbF5U093892@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sat May 24 20:37:15 2014 New Revision: 266629 URL: http://svnweb.freebsd.org/changeset/base/266629 Log: Add a new taskqueue setup method that takes a cpuid to pin the taskqueue worker thread(s) to. For now it isn't a taskqueue/taskthread error to fail to pin to the given cpuid. Thanks to rpaulo@, kib@ and jhb@ for feedback. Tested: * igb(4), with local RSS patches to pin taskqueues. TODO: * ask the doc team for help in documenting the new API call. * add a taskqueue_start_threads_cpuset() method which takes a cpuset_t - but this may require a bunch of surgery to bring cpuset_t into scope. Modified: head/sys/kern/subr_taskqueue.c head/sys/sys/taskqueue.h Modified: head/sys/kern/subr_taskqueue.c ============================================================================== --- head/sys/kern/subr_taskqueue.c Sat May 24 20:31:55 2014 (r266628) +++ head/sys/kern/subr_taskqueue.c Sat May 24 20:37:15 2014 (r266629) @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/cpuset.h> #include <sys/interrupt.h> #include <sys/kernel.h> #include <sys/kthread.h> @@ -496,25 +497,19 @@ taskqueue_swi_giant_run(void *dummy) taskqueue_run(taskqueue_swi_giant); } -int -taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, - const char *name, ...) +static int +_taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, + cpuset_t *mask, const char *ktname) { - va_list ap; struct thread *td; struct taskqueue *tq; int i, error; - char ktname[MAXCOMLEN + 1]; if (count <= 0) return (EINVAL); tq = *tqp; - va_start(ap, name); - vsnprintf(ktname, sizeof(ktname), name, ap); - va_end(ap); - tq->tq_threads = malloc(sizeof(struct thread *) * count, M_TASKQUEUE, M_NOWAIT | M_ZERO); if (tq->tq_threads == NULL) { @@ -542,6 +537,19 @@ taskqueue_start_threads(struct taskqueue if (tq->tq_threads[i] == NULL) continue; td = tq->tq_threads[i]; + if (mask) { + error = cpuset_setthread(curthread->td_tid, mask); + /* + * Failing to pin is rarely an actual fatal error; + * it'll just affect performance. + */ + if (error) + printf("%s: curthread=%llu: can't pin; " + "error=%d\n", + __func__, + (unsigned long long) td->td_tid, + error); + } thread_lock(td); sched_prio(td, pri); sched_add(td, SRQ_BORING); @@ -551,6 +559,45 @@ taskqueue_start_threads(struct taskqueue return (0); } +int +taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, + const char *name, ...) +{ + char ktname[MAXCOMLEN + 1]; + va_list ap; + + va_start(ap, name); + vsnprintf(ktname, sizeof(ktname), name, ap); + va_end(ap); + + return (_taskqueue_start_threads(tqp, count, pri, NULL, ktname)); +} + +int +taskqueue_start_threads_pinned(struct taskqueue **tqp, int count, int pri, + int cpu_id, const char *name, ...) +{ + char ktname[MAXCOMLEN + 1]; + va_list ap; + cpuset_t mask; + + va_start(ap, name); + vsnprintf(ktname, sizeof(ktname), name, ap); + va_end(ap); + + /* + * In case someone passes in NOCPU, just fall back to the + * default behaviour of "don't pin". + */ + if (cpu_id != NOCPU) { + CPU_ZERO(&mask); + CPU_SET(cpu_id, &mask); + } + + return (_taskqueue_start_threads(tqp, count, pri, + cpu_id == NOCPU ? NULL : &mask, ktname)); +} + static inline void taskqueue_run_callback(struct taskqueue *tq, enum taskqueue_callback_type cb_type) Modified: head/sys/sys/taskqueue.h ============================================================================== --- head/sys/sys/taskqueue.h Sat May 24 20:31:55 2014 (r266628) +++ head/sys/sys/taskqueue.h Sat May 24 20:37:15 2014 (r266629) @@ -71,6 +71,10 @@ struct taskqueue *taskqueue_create(const void *context); int taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, const char *name, ...) __printflike(4, 5); +int taskqueue_start_threads_pinned(struct taskqueue **tqp, int count, + int pri, int cpu_id, const char *name, + ...) __printflike(5, 6); + int taskqueue_enqueue(struct taskqueue *queue, struct task *task); int taskqueue_enqueue_timeout(struct taskqueue *queue, struct timeout_task *timeout_task, int ticks);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405242037.s4OKbF5U093892>