From b49efdf4ae873bd405bffbf4279a2c09289c323a Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Fri, 31 Aug 2018 11:12:11 -0700 Subject: [PATCH] thread: Add unit test for channel destruction behavior Change-Id: I8a78a4ad242d1c7fc1af2706d318852315d938ef Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/424263 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Changpeng Liu Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- test/unit/lib/thread/thread.c/thread_ut.c | 58 ++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/test/unit/lib/thread/thread.c/thread_ut.c b/test/unit/lib/thread/thread.c/thread_ut.c index b4a42bcf3..4febbb978 100644 --- a/test/unit/lib/thread/thread.c/thread_ut.c +++ b/test/unit/lib/thread/thread.c/thread_ut.c @@ -463,6 +463,61 @@ channel(void) 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 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_unreg", for_each_channel_unreg) == 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(); return CU_get_error();