thread: Add unit test for channel destruction behavior

Change-Id: I8a78a4ad242d1c7fc1af2706d318852315d938ef
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/424263
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Ben Walker 2018-08-31 11:12:11 -07:00 committed by Jim Harris
parent 8ee5ca50e7
commit b49efdf4ae

View File

@ -463,6 +463,61 @@ channel(void)
CU_ASSERT(TAILQ_EMPTY(&g_threads)); CU_ASSERT(TAILQ_EMPTY(&g_threads));
} }
static int
create_cb(void *io_device, void *ctx_buf)
{
uint64_t *refcnt = (uint64_t *)ctx_buf;
CU_ASSERT(*refcnt == 0);
*refcnt = 1;
return 0;
}
static void
destroy_cb(void *io_device, void *ctx_buf)
{
uint64_t *refcnt = (uint64_t *)ctx_buf;
CU_ASSERT(*refcnt == 1);
*refcnt = 0;
}
/**
* This test is checking that a sequence of get, put, get, put without allowing
* the deferred put operation to complete doesn't result in releasing the memory
* for the channel twice.
*/
static void
channel_destroy_races(void)
{
struct spdk_thread *thread;
uint64_t device;
struct spdk_io_channel *ch;
thread = spdk_allocate_thread(NULL, NULL, NULL, NULL, "thread0");
SPDK_CU_ASSERT_FATAL(thread != NULL);
spdk_io_device_register(&device, create_cb, destroy_cb, sizeof(uint64_t), NULL);
ch = spdk_get_io_channel(&device);
SPDK_CU_ASSERT_FATAL(ch != NULL);
spdk_put_io_channel(ch);
ch = spdk_get_io_channel(&device);
SPDK_CU_ASSERT_FATAL(ch != NULL);
spdk_put_io_channel(ch);
while (spdk_thread_poll(thread, 0) > 0) {}
spdk_io_device_unregister(&device, NULL);
while (spdk_thread_poll(thread, 0) > 0) {}
CU_ASSERT(TAILQ_EMPTY(&g_io_devices));
spdk_free_thread();
CU_ASSERT(TAILQ_EMPTY(&g_threads));
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -487,7 +542,8 @@ main(int argc, char **argv)
CU_add_test(suite, "for_each_channel_remove", for_each_channel_remove) == NULL || CU_add_test(suite, "for_each_channel_remove", for_each_channel_remove) == NULL ||
CU_add_test(suite, "for_each_channel_unreg", for_each_channel_unreg) == NULL || CU_add_test(suite, "for_each_channel_unreg", for_each_channel_unreg) == NULL ||
CU_add_test(suite, "thread_name", thread_name) == NULL || CU_add_test(suite, "thread_name", thread_name) == NULL ||
CU_add_test(suite, "channel", channel) == NULL CU_add_test(suite, "channel", channel) == NULL ||
CU_add_test(suite, "channel_destroy_races", channel_destroy_races) == NULL
) { ) {
CU_cleanup_registry(); CU_cleanup_registry();
return CU_get_error(); return CU_get_error();