Skip site navigation (1)Skip section navigation (2)
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>