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:
parent
04f6e24ae3
commit
515733ca4a
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user