lib/thread: Fail spdk_thread_exit() if thread has active I/O channel
This is a preparation to support voluntary thread termination by calling spdk_thread_exit(). The comment in the header file has already said that all associated I/O channels must be released before calling spdk_thread_exit(). This patch actually checks if it is satisfied in spdk_thread_exit(). Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I56ac50b561c6ca91d3dc2d60c21c8d91d38f081b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/823 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
648d6cd5dd
commit
e038e096e3
@ -349,6 +349,7 @@ int
|
||||
spdk_thread_exit(struct spdk_thread *thread)
|
||||
{
|
||||
struct spdk_poller *poller;
|
||||
struct spdk_io_channel *ch;
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Exit thread %s\n", thread->name);
|
||||
|
||||
@ -382,6 +383,14 @@ spdk_thread_exit(struct spdk_thread *thread)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||
if (ch->ref != 0) {
|
||||
SPDK_ERRLOG("thread %s still has active channel for io_device %s\n",
|
||||
thread->name, ch->dev->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
thread->exit = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -755,7 +755,7 @@ thread_exit(void)
|
||||
bool done1 = false, done2 = false, poller_run = false;
|
||||
int rc __attribute__((unused));
|
||||
|
||||
allocate_threads(5);
|
||||
allocate_threads(6);
|
||||
|
||||
/* Test all pending messages are reaped for the thread marked as exited. */
|
||||
set_thread(0);
|
||||
@ -820,7 +820,7 @@ thread_exit(void)
|
||||
CU_ASSERT(spdk_thread_exit(thread) == 0);
|
||||
CU_ASSERT(spdk_thread_exit(thread) == -EINVAL);
|
||||
|
||||
/* Test if spdk_thread_exit() fails when there is any not-unregistered poller,
|
||||
/* Test if spdk_thread_exit() fails when there is any registered poller,
|
||||
* and if no poller is executed after the thread is marked as exited.
|
||||
*/
|
||||
set_thread(4);
|
||||
@ -847,6 +847,32 @@ thread_exit(void)
|
||||
|
||||
CU_ASSERT(poller_run == false);
|
||||
|
||||
/* Test if spdk_thread_exit() fails when there is any active I/O channel. */
|
||||
set_thread(5);
|
||||
thread = spdk_get_thread();
|
||||
|
||||
spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);
|
||||
|
||||
g_create_cb_calls = 0;
|
||||
ch = spdk_get_io_channel(&g_device1);
|
||||
CU_ASSERT(g_create_cb_calls == 1);
|
||||
CU_ASSERT(ch != NULL);
|
||||
|
||||
CU_ASSERT(spdk_thread_exit(thread) == -EBUSY);
|
||||
|
||||
g_destroy_cb_calls = 0;
|
||||
spdk_put_io_channel(ch);
|
||||
CU_ASSERT(g_destroy_cb_calls == 0);
|
||||
|
||||
CU_ASSERT(spdk_thread_exit(thread) == 0);
|
||||
|
||||
poll_threads();
|
||||
CU_ASSERT(g_destroy_cb_calls == 1);
|
||||
|
||||
spdk_io_device_unregister(&g_device1, NULL);
|
||||
|
||||
CU_ASSERT(TAILQ_EMPTY(&thread->io_channels));
|
||||
|
||||
free_threads();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user