diff --git a/CHANGELOG.md b/CHANGELOG.md index b02346f48..007fc4470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,13 @@ makes it explicit that the default is being used. spdk_bs_io_readv_blob() and spdk_bs_io_writev_blob() were added to enable scattered payloads. +### Event Framework + +The ability to set a thread name, previously only used by the reactor code, is +now part of the `spdk_thread_allocate()` API. Users may specify a thread name +which will show up in tools like `gdb`. + + ## v17.07: Build system improvements, userspace vhost-blk target, and GPT bdev ### Build System diff --git a/examples/bdev/fio_plugin/fio_plugin.c b/examples/bdev/fio_plugin/fio_plugin.c index e104c4b2c..26b2646f3 100644 --- a/examples/bdev/fio_plugin/fio_plugin.c +++ b/examples/bdev/fio_plugin/fio_plugin.c @@ -196,7 +196,7 @@ spdk_fio_init_thread(struct thread_data *td) return -1; } - fio_thread->thread = spdk_allocate_thread(spdk_fio_send_msg, fio_thread); + fio_thread->thread = spdk_allocate_thread(spdk_fio_send_msg, fio_thread, "fio_thread"); if (!fio_thread->thread) { spdk_ring_free(fio_thread->ring); free(fio_thread); diff --git a/include/spdk/io_channel.h b/include/spdk/io_channel.h index 4ea1936fb..67d64f240 100644 --- a/include/spdk/io_channel.h +++ b/include/spdk/io_channel.h @@ -66,8 +66,12 @@ typedef void (*spdk_channel_for_each_cpl)(void *io_device, void *ctx); * called on the same thread that spdk_allocate_thread * was called from. * @param thread_ctx Context that will be passed to fn. + * @param name Human-readable name for the thread; can be retrieved with spdk_thread_get_name(). + * The string is copied, so the pointed-to data only needs to be valid during the + * spdk_allocate_thread() call. May be NULL to specify no name. */ -struct spdk_thread *spdk_allocate_thread(spdk_thread_pass_msg fn, void *thread_ctx); +struct spdk_thread *spdk_allocate_thread(spdk_thread_pass_msg fn, void *thread_ctx, + const char *name); /** * \brief Releases any resources related to the calling thread for I/O channel allocation. @@ -85,6 +89,11 @@ void spdk_free_thread(void); */ struct spdk_thread *spdk_get_thread(void); +/** + * \brief Get a thread's name. + */ +const char *spdk_thread_get_name(const struct spdk_thread *thread); + /** * \brief Send a message to the given thread. The message * may be sent asynchronously - i.e. spdk_thread_send_msg diff --git a/lib/event/reactor.c b/lib/event/reactor.c index 103043709..1e54e7dff 100644 --- a/lib/event/reactor.c +++ b/lib/event/reactor.c @@ -36,14 +36,6 @@ #include "spdk_internal/event.h" #include "spdk_internal/log.h" -#ifdef __linux__ -#include -#endif - -#ifdef __FreeBSD__ -#include -#endif - #include "spdk/log.h" #include "spdk/io_channel.h" #include "spdk/env.h" @@ -207,27 +199,6 @@ _spdk_event_queue_run_batch(struct spdk_reactor *reactor) return count; } -/** - * - * \brief Set current reactor thread name to "reactor ". - * - * This makes the reactor threads distinguishable in top and gdb. - */ -static void set_reactor_thread_name(uint32_t lcore) -{ - char thread_name[16]; - - snprintf(thread_name, sizeof(thread_name), "reactor_%u", lcore); - -#if defined(__linux__) - prctl(PR_SET_NAME, thread_name, 0, 0, 0); -#elif defined(__FreeBSD__) - pthread_set_name_np(pthread_self(), thread_name); -#else -#error missing platform support for thread name -#endif -} - static void spdk_poller_insert_timer(struct spdk_reactor *reactor, struct spdk_poller *poller, uint64_t now) { @@ -335,9 +306,10 @@ _spdk_reactor_run(void *arg) uint64_t spin_cycles, sleep_cycles; uint32_t sleep_us; uint32_t timer_poll_count; + char thread_name[32]; - spdk_allocate_thread(_spdk_reactor_send_msg, &reactor->lcore); - set_reactor_thread_name(reactor->lcore); + snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore); + spdk_allocate_thread(_spdk_reactor_send_msg, &reactor->lcore, thread_name); SPDK_NOTICELOG("Reactor started on core %u on socket %u\n", reactor->lcore, reactor->socket_id); diff --git a/lib/rocksdb/env_spdk.cc b/lib/rocksdb/env_spdk.cc index 0facd620b..a7657bb3b 100644 --- a/lib/rocksdb/env_spdk.cc +++ b/lib/rocksdb/env_spdk.cc @@ -440,7 +440,7 @@ _spdk_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) void SpdkInitializeThread(void) { if (g_fs != NULL) { - spdk_allocate_thread(_spdk_send_msg, NULL); + spdk_allocate_thread(_spdk_send_msg, NULL, "spdk_rocksdb"); g_sync_args.channel = spdk_fs_alloc_io_channel_sync(g_fs); } } @@ -481,7 +481,6 @@ spdk_rocksdb_run(void *arg1, void *arg2) { struct spdk_bdev *bdev; - pthread_setname_np(pthread_self(), "spdk"); bdev = spdk_bdev_get_by_name(g_bdev_name.c_str()); if (bdev == NULL) { diff --git a/lib/util/io_channel.c b/lib/util/io_channel.c index ecb2e980a..e2b3c12b5 100644 --- a/lib/util/io_channel.c +++ b/lib/util/io_channel.c @@ -36,6 +36,14 @@ #include "spdk/io_channel.h" #include "spdk/log.h" +#ifdef __linux__ +#include +#endif + +#ifdef __FreeBSD__ +#include +#endif + static pthread_mutex_t g_devlist_mutex = PTHREAD_MUTEX_INITIALIZER; struct io_device { @@ -72,6 +80,7 @@ struct spdk_thread { void *thread_ctx; TAILQ_HEAD(, spdk_io_channel) io_channels; TAILQ_ENTRY(spdk_thread) tailq; + char *name; }; static TAILQ_HEAD(, spdk_thread) g_threads = TAILQ_HEAD_INITIALIZER(g_threads); @@ -94,8 +103,20 @@ _get_thread(void) return NULL; } +static void +_set_thread_name(const char *thread_name) +{ +#if defined(__linux__) + prctl(PR_SET_NAME, thread_name, 0, 0, 0); +#elif defined(__FreeBSD__) + pthread_set_name_np(pthread_self(), thread_name); +#else +#error missing platform support for thread name +#endif +} + struct spdk_thread * -spdk_allocate_thread(spdk_thread_pass_msg fn, void *thread_ctx) +spdk_allocate_thread(spdk_thread_pass_msg fn, void *thread_ctx, const char *name) { struct spdk_thread *thread; @@ -120,6 +141,10 @@ spdk_allocate_thread(spdk_thread_pass_msg fn, void *thread_ctx) thread->thread_ctx = thread_ctx; TAILQ_INIT(&thread->io_channels); TAILQ_INSERT_TAIL(&g_threads, thread, tailq); + if (name) { + _set_thread_name(name); + thread->name = strdup(name); + } pthread_mutex_unlock(&g_devlist_mutex); @@ -141,6 +166,7 @@ spdk_free_thread(void) } TAILQ_REMOVE(&g_threads, thread, tailq); + free(thread->name); free(thread); pthread_mutex_unlock(&g_devlist_mutex); @@ -163,6 +189,12 @@ spdk_get_thread(void) return thread; } +const char * +spdk_thread_get_name(const struct spdk_thread *thread) +{ + return thread->name; +} + void spdk_thread_send_msg(const struct spdk_thread *thread, spdk_thread_fn fn, void *ctx) { diff --git a/test/lib/blobfs/blobfs_async_ut/blobfs_async_ut.c b/test/lib/blobfs/blobfs_async_ut/blobfs_async_ut.c index b0e978dcb..2e3b5acba 100644 --- a/test/lib/blobfs/blobfs_async_ut/blobfs_async_ut.c +++ b/test/lib/blobfs/blobfs_async_ut/blobfs_async_ut.c @@ -73,7 +73,7 @@ fs_init(void) struct spdk_bs_dev *dev; dev = init_dev(); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); CU_ASSERT(g_fs != NULL); @@ -117,7 +117,7 @@ fs_open(void) dev = init_dev(); memset(name, 'a', sizeof(name) - 1); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); CU_ASSERT(g_fs != NULL); @@ -186,7 +186,7 @@ fs_create(void) dev = init_dev(); memset(name, 'a', sizeof(name) - 1); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); SPDK_CU_ASSERT_FATAL(g_fs != NULL); @@ -225,7 +225,7 @@ fs_truncate(void) struct spdk_bs_dev *dev; dev = init_dev(); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); SPDK_CU_ASSERT_FATAL(g_fs != NULL); @@ -278,7 +278,7 @@ fs_rename(void) struct spdk_bs_dev *dev; dev = init_dev(); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); SPDK_CU_ASSERT_FATAL(g_fs != NULL); @@ -431,7 +431,7 @@ channel_ops(void) struct spdk_io_channel *channel; dev = init_dev(); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); SPDK_CU_ASSERT_FATAL(g_fs != NULL); @@ -459,7 +459,7 @@ channel_ops_sync(void) struct spdk_io_channel *channel; dev = init_dev(); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); spdk_fs_init(dev, NULL, fs_op_with_handle_complete, NULL); SPDK_CU_ASSERT_FATAL(g_fs != NULL); diff --git a/test/lib/blobfs/blobfs_sync_ut/blobfs_sync_ut.c b/test/lib/blobfs/blobfs_sync_ut/blobfs_sync_ut.c index 91e61c789..a89a2fcd8 100644 --- a/test/lib/blobfs/blobfs_sync_ut/blobfs_sync_ut.c +++ b/test/lib/blobfs/blobfs_sync_ut/blobfs_sync_ut.c @@ -158,7 +158,7 @@ cache_write(void) ut_send_request(_fs_init, NULL); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); channel = spdk_fs_alloc_io_channel_sync(g_fs); rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file); @@ -196,7 +196,7 @@ cache_write_null_buffer(void) ut_send_request(_fs_init, NULL); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); channel = spdk_fs_alloc_io_channel_sync(g_fs); rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file); @@ -227,7 +227,7 @@ fs_create_sync(void) ut_send_request(_fs_init, NULL); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); channel = spdk_fs_alloc_io_channel_sync(g_fs); CU_ASSERT(channel != NULL); @@ -256,7 +256,7 @@ cache_append_no_cache(void) ut_send_request(_fs_init, NULL); - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); channel = spdk_fs_alloc_io_channel_sync(g_fs); rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file); @@ -298,7 +298,7 @@ spdk_thread(void *arg) { struct ut_request *req; - spdk_allocate_thread(_fs_send_msg, NULL); + spdk_allocate_thread(_fs_send_msg, NULL, "thread0"); while (1) { pthread_mutex_lock(&g_mutex); diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 0cd9ef638..f80813c67 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -1218,7 +1218,7 @@ int main(int argc, char **argv) } g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); - spdk_allocate_thread(_bs_send_msg, NULL); + spdk_allocate_thread(_bs_send_msg, NULL, "thread0"); CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests(); num_failures = CU_get_number_of_failures(); diff --git a/test/unit/lib/util/io_channel.c/io_channel_ut.c b/test/unit/lib/util/io_channel.c/io_channel_ut.c index 1022c2f26..cf9b027a9 100644 --- a/test/unit/lib/util/io_channel.c/io_channel_ut.c +++ b/test/unit/lib/util/io_channel.c/io_channel_ut.c @@ -46,7 +46,24 @@ _send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) static void thread_alloc(void) { - spdk_allocate_thread(_send_msg, NULL); + struct spdk_thread *thread; + const char *name; + + /* Create thread with no name */ + spdk_allocate_thread(_send_msg, NULL, NULL); + thread = spdk_get_thread(); + SPDK_CU_ASSERT_FATAL(thread != NULL); + name = spdk_thread_get_name(thread); + CU_ASSERT(name == NULL); + spdk_free_thread(); + + /* Create thread named "test_thread" */ + spdk_allocate_thread(_send_msg, NULL, "test_thread"); + thread = spdk_get_thread(); + SPDK_CU_ASSERT_FATAL(thread != NULL); + name = spdk_thread_get_name(thread); + SPDK_CU_ASSERT_FATAL(name != NULL); + CU_ASSERT(strcmp(name, "test_thread") == 0); spdk_free_thread(); } @@ -106,7 +123,7 @@ channel(void) struct spdk_io_channel *ch1, *ch2; void *ctx; - spdk_allocate_thread(_send_msg, NULL); + spdk_allocate_thread(_send_msg, NULL, "thread0"); spdk_io_device_register(&device1, create_cb_1, destroy_cb_1, sizeof(ctx1)); spdk_io_device_register(&device2, create_cb_2, destroy_cb_2, sizeof(ctx2)); spdk_io_device_register(&device3, create_cb_null, NULL, 0);