diff options
author | Richard Braun <rbraun@sceen.net> | 2019-01-10 23:27:59 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2019-01-10 23:27:59 +0100 |
commit | 5ce63fc5a34b3be947120478a9aa0a00d071257f (patch) | |
tree | 354dc92bd3db93dfb274a07ac91b7d451c3b0053 | |
parent | 9b40330cdc9399acb3687cbccb7696b4fd9feb0e (diff) |
test/test_semaphore: new module
-rw-r--r-- | test/Kconfig | 3 | ||||
-rw-r--r-- | test/Makefile | 1 | ||||
-rw-r--r-- | test/test_semaphore.c | 111 |
3 files changed, 115 insertions, 0 deletions
diff --git a/test/Kconfig b/test/Kconfig index d3cd9b5e..0d8fee90 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -52,6 +52,9 @@ config TEST_MODULE_PMAP_UPDATE_MP config TEST_MODULE_RCU_DEFER bool "rcu_defer" +config TEST_MODULE_SEMAPHORE + bool "semaphore" + config TEST_MODULE_SREF_DIRTY_ZEROES bool "sref_dirty_zeroes" diff --git a/test/Makefile b/test/Makefile index 81e615cf..b80a9033 100644 --- a/test/Makefile +++ b/test/Makefile @@ -7,6 +7,7 @@ x15_SOURCES-$(CONFIG_TEST_MODULE_PERFMON_THREAD) += test/test_perfmon_thr x15_SOURCES-$(CONFIG_TEST_MODULE_PERFMON_TORTURE) += test/test_perfmon_torture.c x15_SOURCES-$(CONFIG_TEST_MODULE_PMAP_UPDATE_MP) += test/test_pmap_update_mp.c x15_SOURCES-$(CONFIG_TEST_MODULE_RCU_DEFER) += test/test_rcu_defer.c +x15_SOURCES-$(CONFIG_TEST_MODULE_SEMAPHORE) += test/test_semaphore.c x15_SOURCES-$(CONFIG_TEST_MODULE_SREF_DIRTY_ZEROES) += test/test_sref_dirty_zeroes.c x15_SOURCES-$(CONFIG_TEST_MODULE_SREF_NOREF) += test/test_sref_noref.c x15_SOURCES-$(CONFIG_TEST_MODULE_SREF_WEAKREF) += test/test_sref_weakref.c diff --git a/test/test_semaphore.c b/test/test_semaphore.c new file mode 100644 index 00000000..299273ea --- /dev/null +++ b/test/test_semaphore.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2019 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * This test creates a number of threads (at least 2) which wait on a + * semaphore, and one that posts the semaphore as many times as there + * are threads. All threads are bound to the same processor, and posts + * are performed with preemption disabled, to guarantee they occur + * back-to-back in order to make sure that they're not missed. + */ + +#include <stddef.h> +#include <stdio.h> + +#include <kern/cpumap.h> +#include <kern/error.h> +#include <kern/log.h> +#include <kern/macros.h> +#include <kern/semaphore.h> +#include <kern/thread.h> +#include <test/test.h> + +#define TEST_NR_WAITERS 2 + +#if TEST_NR_WAITERS < 2 +#error "invalid number of waiters" +#endif /* TEST_NR_WAITERS < 2 */ + +static struct semaphore test_semaphore; + +static struct thread *test_waiters[TEST_NR_WAITERS]; + +static void +test_wait(void *arg) +{ + (void)arg; + + semaphore_wait(&test_semaphore); +} + +static void +test_post(void *arg) +{ + int error; + + (void)arg; + + for (size_t i = 0; i < ARRAY_SIZE(test_waiters); i++) { + while (thread_state(test_waiters[i]) != THREAD_SLEEPING) { + thread_delay(1, false); + } + } + + thread_preempt_disable(); + + for (size_t i = 0; i < ARRAY_SIZE(test_waiters); i++) { + error = semaphore_post(&test_semaphore); + error_check(error, "semaphore_post"); + } + + thread_preempt_enable(); + + for (size_t i = 0; i < ARRAY_SIZE(test_waiters); i++) { + thread_join(test_waiters[i]); + } + + log_info("test: done"); +} + +void __init +test_setup(void) +{ + char name[THREAD_NAME_SIZE]; + struct thread_attr attr; + struct cpumap *cpumap; + int error; + + semaphore_init(&test_semaphore, 0, TEST_NR_WAITERS); + + error = cpumap_create(&cpumap); + error_check(error, "cpumap_create"); + cpumap_zero(cpumap); + cpumap_set(cpumap, 0); + + for (size_t i = 0; i < ARRAY_SIZE(test_waiters); i++) { + snprintf(name, sizeof(name), THREAD_KERNEL_PREFIX "test_wait:%zu", i); + thread_attr_init(&attr, name); + thread_attr_set_cpumap(&attr, cpumap); + error = thread_create(&test_waiters[i], &attr, test_wait, NULL); + error_check(error, "thread_create"); + } + + thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_post"); + thread_attr_set_detached(&attr); + thread_attr_set_cpumap(&attr, cpumap); + error = thread_create(NULL, &attr, test_post, NULL); + error_check(error, "thread_create"); +} |