From 713aafbc10e062a28c198557a559590466ec59a0 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Sun, 23 Feb 2020 18:02:53 -0500 Subject: [PATCH] lib/thread: Add spdk_thread_set_cpumask() and enum SPDK_THREAD_OP_RESCHED Add an new API spdk_thread_set_cpumask() and enum SPDK_THREAD_OP_RESCHED. spdk_thread_set_cpumask() can be called only from the current thread and requires SPDK thread operation supports reschedule operation. spdk_thread_set_cpumask() updates the cpumask of the current thread to the specified value, and then invokes framework's reschedule operation to the thread. If spdk_thread_set_cpumask() calls multiple times in a single spdk_thread_poll() context, the last value will be used in the reschedule operation. Signed-off-by: Shuhei Matsumoto Change-Id: I7808626b10269543c1e2cd86793a504daa4b6389 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/499 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/thread.h | 17 +++++++++++++++++ lib/thread/thread.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/spdk/thread.h b/include/spdk/thread.h index e74967eab..0626c5773 100644 --- a/include/spdk/thread.h +++ b/include/spdk/thread.h @@ -76,6 +76,11 @@ enum spdk_thread_op { * should frequently call spdk_thread_poll() on the thread provided. */ SPDK_THREAD_OP_NEW, + + /* Called when SPDK thread needs to be rescheduled. (e.g., when cpumask of the + * SPDK thread is updated. + */ + SPDK_THREAD_OP_RESCHED, }; /** @@ -309,6 +314,18 @@ void *spdk_thread_get_ctx(struct spdk_thread *thread); */ struct spdk_cpuset *spdk_thread_get_cpumask(struct spdk_thread *thread); +/** + * Set the current thread's cpumask to the specified value. The thread may be + * rescheduled to one of the CPUs specified in the cpumask. + * + * This API requires SPDK thread operation supports SPDK_THREAD_OP_RESCHED. + * + * \param cpumask The new cpumask for the thread. + * + * \return 0 on success, negated errno otherwise. + */ +int spdk_thread_set_cpumask(struct spdk_cpuset *cpumask); + /** * Return the thread object associated with the context handle previously * obtained by calling spdk_thread_get_ctx(). diff --git a/lib/thread/thread.c b/lib/thread/thread.c index 9c1b89746..fbc25e2ba 100644 --- a/lib/thread/thread.c +++ b/lib/thread/thread.c @@ -479,6 +479,35 @@ spdk_thread_get_cpumask(struct spdk_thread *thread) return &thread->cpumask; } +int +spdk_thread_set_cpumask(struct spdk_cpuset *cpumask) +{ + struct spdk_thread *thread; + + if (!g_thread_op_supported_fn || !g_thread_op_supported_fn(SPDK_THREAD_OP_RESCHED)) { + SPDK_ERRLOG("Framework does not support reschedule operation.\n"); + assert(false); + return -ENOTSUP; + } + + thread = spdk_get_thread(); + if (!thread) { + SPDK_ERRLOG("Called from non-SPDK thread\n"); + assert(false); + return -EINVAL; + } + + spdk_cpuset_copy(&thread->cpumask, cpumask); + + /* Invoke framework's reschedule operation. If this function is called multiple times + * in a single spdk_thread_poll() context, the last cpumask will be used in the + * reschedule operation. + */ + g_thread_op_fn(thread, SPDK_THREAD_OP_RESCHED); + + return 0; +} + struct spdk_thread * spdk_thread_get_from_ctx(void *ctx) {