lib/thread: Add unique ID for each created SPDK thread

Add an unique ID for each created SPDK thread. Use a single 64 bits
variable, g_thread_id, and guard its update by the global mutex
g_devlist_mutex. For our safety, further thread creation is not
allowed if g_thread_id rolls over, and request user to restart SPDK
application.

Besides, as a minor update, move the debug log down and add ID to it
in spdk_thread_create(), and ID is added to thread_get_stats RPC and
framework_get_reactors RPC.

The thread ID will be used to set the cpumask of the running thread
to the specified value in the subsequent patches.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ic09f11d4c7175c3b89acba6a42e76063acd0d1a0
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/498
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-02-04 00:02:46 -05:00 committed by Tomasz Zawadzki
parent 04f6e24ae3
commit 515733ca4a
5 changed files with 39 additions and 6 deletions

View File

@ -520,6 +520,7 @@ Example response:
"lw_threads": [
{
"name": "app_thread",
"id", 1,
"cpumask": "1"
}
]
@ -563,6 +564,7 @@ Example response:
"threads": [
{
"name": "app_thread",
"id": 1,
"cpumask": "1",
"busy": 139223208,
"idle": 8641080608

View File

@ -363,6 +363,15 @@ struct spdk_thread *spdk_get_thread(void);
*/
const char *spdk_thread_get_name(const struct spdk_thread *thread);
/**
* Get a thread's ID.
*
* \param thread Thread to query.
*
* \return the ID of the thread..
*/
uint64_t spdk_thread_get_id(const struct spdk_thread *thread);
struct spdk_thread_stats {
uint64_t busy_tsc;
uint64_t idle_tsc;

View File

@ -51,6 +51,11 @@ static pthread_mutex_t g_devlist_mutex = PTHREAD_MUTEX_INITIALIZER;
static spdk_new_thread_fn g_new_thread_fn = NULL;
static size_t g_ctx_sz = 0;
/* Monotonic increasing ID is set to each created thread beginning at 1. Once the
* ID exceeds UINT64_MAX, further thread creation is not allowed and restarting
* SPDK application is required.
*/
static uint64_t g_thread_id = 1;
struct io_device {
void *io_device;
@ -118,6 +123,7 @@ struct spdk_thread {
TAILQ_HEAD(, spdk_io_channel) io_channels;
TAILQ_ENTRY(spdk_thread) tailq;
char name[SPDK_MAX_THREAD_NAME_LEN + 1];
uint64_t id;
bool exit;
@ -321,13 +327,21 @@ spdk_thread_create(const char *name, struct spdk_cpuset *cpumask)
snprintf(thread->name, sizeof(thread->name), "%p", thread);
}
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Allocating new thread %s\n", thread->name);
pthread_mutex_lock(&g_devlist_mutex);
if (g_thread_id == 0) {
SPDK_ERRLOG("Thread ID rolled over. Further thread creation is not allowed.\n");
pthread_mutex_unlock(&g_devlist_mutex);
_free_thread(thread);
return NULL;
}
thread->id = g_thread_id++;
TAILQ_INSERT_TAIL(&g_threads, thread, tailq);
g_thread_count++;
pthread_mutex_unlock(&g_devlist_mutex);
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Allocating new thread (%" PRIu64 ", %s)\n",
thread->id, thread->name);
if (g_new_thread_fn) {
rc = g_new_thread_fn(thread);
if (rc != 0) {
@ -715,6 +729,12 @@ spdk_thread_get_name(const struct spdk_thread *thread)
return thread->name;
}
uint64_t
spdk_thread_get_id(const struct spdk_thread *thread)
{
return thread->id;
}
int
spdk_thread_get_stats(struct spdk_thread_stats *stats)
{

View File

@ -180,6 +180,7 @@ rpc_thread_get_stats(void *arg)
if (0 == spdk_thread_get_stats(&stats)) {
spdk_json_write_object_begin(ctx->w);
spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
spdk_json_write_named_string(ctx->w, "cpumask",
spdk_cpuset_fmt(spdk_thread_get_cpumask(thread)));
spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
@ -251,6 +252,7 @@ rpc_framework_get_reactors(void *arg1, void *arg2)
spdk_json_write_object_begin(ctx->w);
spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
spdk_json_write_named_string(ctx->w, "cpumask",
spdk_cpuset_fmt(spdk_thread_get_cpumask(thread)));
spdk_json_write_object_end(ctx->w);

View File

@ -61,12 +61,12 @@ struct ut_thread *g_ut_threads;
#define INVALID_THREAD 0x1000
static uint64_t g_thread_id = INVALID_THREAD;
static uint64_t g_ut_thread_id = INVALID_THREAD;
static void
set_thread(uintptr_t thread_id)
{
g_thread_id = thread_id;
g_ut_thread_id = thread_id;
if (thread_id == INVALID_THREAD) {
spdk_set_thread(NULL);
} else {
@ -138,7 +138,7 @@ poll_thread_times(uintptr_t thread_id, uint32_t max_polls)
assert(thread_id != (uintptr_t)INVALID_THREAD);
assert(thread_id < g_ut_num_threads);
original_thread_id = g_thread_id;
original_thread_id = g_ut_thread_id;
set_thread(INVALID_THREAD);
while (polls_executed < max_polls) {
@ -163,7 +163,7 @@ poll_thread(uintptr_t thread_id)
assert(thread_id != (uintptr_t)INVALID_THREAD);
assert(thread_id < g_ut_num_threads);
original_thread_id = g_thread_id;
original_thread_id = g_ut_thread_id;
set_thread(INVALID_THREAD);
while (spdk_thread_poll(thread->thread, 0, 0) > 0) {