From owner-svn-src-head@FreeBSD.ORG Sat May 24 20:37:16 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 325BEF6C; Sat, 24 May 2014 20:37:16 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1EFF02B72; Sat, 24 May 2014 20:37:16 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4OKbFha093894; Sat, 24 May 2014 20:37:15 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4OKbF5U093892; Sat, 24 May 2014 20:37:15 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201405242037.s4OKbF5U093892@svn.freebsd.org> From: Adrian Chadd Date: Sat, 24 May 2014 20:37:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266629 - in head/sys: kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 May 2014 20:37:16 -0000 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 #include #include +#include #include #include #include @@ -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);