From c570efd63b6f6f24259a39e553a1d6e71ffef825 Mon Sep 17 00:00:00 2001 From: Sharron LIU Date: Wed, 28 Dec 2016 11:39:00 +0800 Subject: [PATCH] tests: kernel: added memory pool threadsafe test TestPurpose: verify API thread safe in multi-threads environment. Jira: ZEP-1210 Change-Id: I1ff8231db8ebcd5713d6083379d0ebfbdabeeee0 Signed-off-by: Sharron LIU --- .../mem_pool/test_mpool_threadsafe/Makefile | 4 + .../mem_pool/test_mpool_threadsafe/prj.conf | 4 + .../test_mpool_threadsafe/src/Makefile | 3 + .../mem_pool/test_mpool_threadsafe/src/main.c | 27 +++++ .../src/test_mpool_threadsafe.c | 109 ++++++++++++++++++ .../test_mpool_threadsafe/testcase.ini | 2 + 6 files changed, 149 insertions(+) create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/Makefile create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/prj.conf create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/src/Makefile create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/src/main.c create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/src/test_mpool_threadsafe.c create mode 100644 tests/kernel/mem_pool/test_mpool_threadsafe/testcase.ini diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/Makefile b/tests/kernel/mem_pool/test_mpool_threadsafe/Makefile new file mode 100644 index 00000000000..e70a750a88d --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.test diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/prj.conf b/tests/kernel/mem_pool/test_mpool_threadsafe/prj.conf new file mode 100644 index 00000000000..a508d3161c6 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +# 1 millisecond +CONFIG_TIMESLICE_SIZE=1 diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/src/Makefile b/tests/kernel/mem_pool/test_mpool_threadsafe/src/Makefile new file mode 100644 index 00000000000..abcea85ec5d --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/src/Makefile @@ -0,0 +1,3 @@ +include $(ZEPHYR_BASE)/tests/Makefile.test + +obj-y = main.o test_mpool_threadsafe.o diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/src/main.c b/tests/kernel/mem_pool/test_mpool_threadsafe/src/main.c new file mode 100644 index 00000000000..3763edced77 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/src/main.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +extern void test_mpool_threadsafe(void); + +/*test case main entry*/ +void test_main(void *p1, void *p2, void *p3) +{ + ztest_test_suite(test_mpool_threadsafe, + ztest_unit_test(test_mpool_threadsafe)); + ztest_run_test_suite(test_mpool_threadsafe); +} diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/src/test_mpool_threadsafe.c b/tests/kernel/mem_pool/test_mpool_threadsafe/src/test_mpool_threadsafe.c new file mode 100644 index 00000000000..397ca1abc4d --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/src/test_mpool_threadsafe.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup t_mpool + * @{ + * @defgroup t_mpool_threadsafe test_mpool_threadsafe + * @brief TestPurpose: verify API thread safe in multi-threads environment. + * @details This's an extensive test. Multiple threads in same priority are + * created, with time slice scheduling enabled in a very small slicing size: + * 1 millisecond (refer to prj.conf). + * All threads share a same entry function to invoke same kernel APIs. + * Unless explicitly stated, kernel APIs are supposed to be thread safe. + * Expect all threads should complete and exit the entry function normally. + * + * NOTE: + * # API functionality is not TESTPOINT here. When invoked by multiple + * threads, each API following its own behavior specification returns either + * success or failure. Like, memory allocation successful or fail is pending on + * whether any free memory blocks are available at the moment when the API is + * invoked by a thread just got scheduled in. + * # For kernel object APIs, more than one instance of the same object type are + * created. Like, 4 threads operating on 2 instances, the test would cover the + * kernel's code branches that handling "multiple threads accessing to a same + * instance" and that handling "multiple instances serving simultaneously". + * # The test adopts a slicing size in 1 millisecond. Thread safe theoretically + * should work in a smaller slicing size. But this does not intent to stress + * test that. + * @} + */ + +#include +#include +#define THREAD_NUM 4 +#define STACK_SIZE 512 +#define POOL_NUM 2 +#define TIMEOUT 200 +#define BLK_SIZE_MIN 4 +#define BLK_SIZE_MAX 16 +#define BLK_NUM_MIN 8 +#define BLK_NUM_MAX 2 +#define BLK_ALIGN BLK_SIZE_MIN + +K_MEM_POOL_DEFINE(mpool1, BLK_SIZE_MIN, BLK_SIZE_MAX, BLK_NUM_MAX, BLK_ALIGN); +K_MEM_POOL_DEFINE(mpool2, BLK_SIZE_MIN, BLK_SIZE_MAX, BLK_NUM_MAX, BLK_ALIGN); +static char __noinit __stack tstack[THREAD_NUM][STACK_SIZE]; +static struct k_mem_pool *pools[POOL_NUM] = {&mpool1, &mpool2}; +static struct k_sem sync_sema; +static atomic_t pool_id; + +/* thread entry simply invoke the APIs*/ +static void tmpool_api(void *p1, void *p2, void *p3) +{ + struct k_mem_block block[BLK_NUM_MIN]; + struct k_mem_pool *pool = pools[atomic_inc(&pool_id) % POOL_NUM]; + + memset(block, 0, sizeof(block)); + + for (int i = 0; i < 4; i++) { + k_mem_pool_alloc(pool, &block[i], BLK_SIZE_MIN, TIMEOUT); + } + k_mem_pool_alloc(pool, &block[4], BLK_SIZE_MAX, TIMEOUT); + for (int i = 0; i < 5; i++) { + if (block[i].data) { + k_mem_pool_free(&block[i]); + block[i].data = NULL; + } + } + k_mem_pool_defrag(pool); + + k_sem_give(&sync_sema); +} + +/* test cases*/ +void test_mpool_threadsafe(void) +{ + k_tid_t tid[THREAD_NUM]; + + k_sem_init(&sync_sema, 0, THREAD_NUM); + + /* create multiple threads to invoke same memory pool APIs*/ + for (int i = 0; i < THREAD_NUM; i++) { + tid[i] = k_thread_spawn(tstack[i], STACK_SIZE, + tmpool_api, NULL, NULL, NULL, + K_PRIO_PREEMPT(1), 0, 0); + } + /* TESTPOINT: all threads complete and exit the entry function*/ + for (int i = 0; i < THREAD_NUM; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } + + /* test case tear down*/ + for (int i = 0; i < THREAD_NUM; i++) { + k_thread_abort(tid[i]); + } +} diff --git a/tests/kernel/mem_pool/test_mpool_threadsafe/testcase.ini b/tests/kernel/mem_pool/test_mpool_threadsafe/testcase.ini new file mode 100644 index 00000000000..58c4d1a1747 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_threadsafe/testcase.ini @@ -0,0 +1,2 @@ +[test] +tags = kernel