svn commit: r266629 - in head/sys: kern sys
Adrian Chadd
adrian at FreeBSD.org
Sat May 24 20:37:16 UTC 2014
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);
More information about the svn-src-all
mailing list