diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index d524503563..7ec2e73838 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -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 diff --git a/include/spdk/thread.h b/include/spdk/thread.h index 90ec4ecc1f..90c96c31b3 100644 --- a/include/spdk/thread.h +++ b/include/spdk/thread.h @@ -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; diff --git a/lib/thread/thread.c b/lib/thread/thread.c index 6165a77fbe..5db66b708d 100644 --- a/lib/thread/thread.c +++ b/lib/thread/thread.c @@ -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) { diff --git a/module/event/rpc/app_rpc.c b/module/event/rpc/app_rpc.c index 6211f52274..b4ee321f25 100644 --- a/module/event/rpc/app_rpc.c +++ b/module/event/rpc/app_rpc.c @@ -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); diff --git a/test/common/lib/ut_multithread.c b/test/common/lib/ut_multithread.c index 396e4ac719..0b72c8b72f 100644 --- a/test/common/lib/ut_multithread.c +++ b/test/common/lib/ut_multithread.c @@ -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) {