summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-16 16:54:56 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-24 15:20:57 +0100
commit5bcdc25e72c9d8f446c86becf277e7e11899e79b (patch)
tree65775fdeb550c6444d840998ed9101c0141a43d5
parentCONDVAR(9): Use FreeBSD implementation (diff)
downloadrtems-libbsd-5bcdc25e72c9d8f446c86becf277e7e11899e79b.tar.bz2
smp01: New test
-rw-r--r--Makefile12
-rwxr-xr-xfreebsd-to-rtems.py1
-rw-r--r--testsuite/smp01/test_main.c289
3 files changed, 302 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 4ca3d216..8753efeb 100644
--- a/Makefile
+++ b/Makefile
@@ -1399,6 +1399,18 @@ $(TEST_ZEROCOPY01): $(TEST_ZEROCOPY01_O_FILES) $(LIB)
NET_TESTS += $(TEST_ZEROCOPY01)
O_FILES += $(TEST_ZEROCOPY01_O_FILES)
D_FILES += $(TEST_ZEROCOPY01_D_FILES)
+
+TEST_SMP01 = testsuite/smp01/smp01.exe
+TEST_SMP01_O_FILES =
+TEST_SMP01_D_FILES =
+TEST_SMP01_O_FILES += testsuite/smp01/test_main.o
+TEST_SMP01_D_FILES += testsuite/smp01/test_main.d
+$(TEST_SMP01): $(TEST_SMP01_O_FILES) $(LIB)
+ $(LINK.c) -Wl,-Map,testsuite/smp01/smp01.map $^ -lm -lz -o $@
+TESTS += $(TEST_SMP01)
+O_FILES += $(TEST_SMP01_O_FILES)
+D_FILES += $(TEST_SMP01_D_FILES)
+RUN_TESTS += $(TEST_SMP01)
LIB_C_FILES += dhcpcd/arp.c
dhcpcd/arp.o: dhcpcd/arp.c
$(CC) $(CPPFLAGS) $(CFLAGS) -D__FreeBSD__ -DTHERE_IS_NO_FORK -DMASTER_ONLY -DINET -DINET6 -c $< -o $@
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index 66518c4d..b91f7680 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -2515,6 +2515,7 @@ tests.addTest('mutex01', ['test_main'])
tests.addTest('condvar01', ['test_main'])
tests.addTest('ppp01', ['test_main'], runTest = False)
tests.addTest('zerocopy01', ['test_main'], runTest = False, netTest = True)
+tests.addTest('smp01', ['test_main'])
dhcpcd = Module('dhcpcd')
dhcpcd.addSourceFiles(
diff --git a/testsuite/smp01/test_main.c b/testsuite/smp01/test_main.c
new file mode 100644
index 00000000..0b8ea2c5
--- /dev/null
+++ b/testsuite/smp01/test_main.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/rtems-bsd-kernel-space.h>
+
+#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/types.h>
+#include <sys/systm.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/test.h>
+
+#define TEST_NAME "LIBBSD SMP 1"
+
+#define CPU_COUNT 32
+
+#define OBJ_COUNT (CPU_COUNT / 2)
+
+typedef struct {
+ uint32_t mtx_lock[CPU_COUNT];
+ uint32_t mtx_try_success[CPU_COUNT];
+ uint32_t mtx_try_failed[CPU_COUNT];
+ uint32_t cv_signal[CPU_COUNT];
+ uint32_t cv_broadcast[CPU_COUNT];
+ uint32_t cv_timedwait_success[CPU_COUNT];
+ uint32_t cv_timedwait_timeout[CPU_COUNT];
+} test_stats;
+
+typedef struct {
+ rtems_test_parallel_context base;
+ struct mtx mtx[OBJ_COUNT];
+ struct cv cv[OBJ_COUNT];
+ volatile uint32_t value[OBJ_COUNT];
+ test_stats stats;
+} test_context;
+
+static test_context test_instance;
+
+static rtems_interval
+test_duration(void)
+{
+
+ return (10 * rtems_clock_get_ticks_per_second());
+}
+
+static uint32_t
+simple_random(uint32_t v)
+{
+ v *= 1664525;
+ v += 1013904223;
+
+ return (v);
+}
+
+static rtems_interval
+test_init(rtems_test_parallel_context *base, void *arg, size_t active_workers)
+{
+
+ return (test_duration());
+}
+
+static void
+test_fini(rtems_test_parallel_context *base, void *arg, size_t active_workers)
+{
+
+ /* Do nothing */
+}
+
+static void
+busy(void)
+{
+ int i;
+
+ for (i = 0; i < 1000; ++i) {
+ __asm__ volatile ("");
+ }
+}
+
+static uint32_t
+get_obj_count(void)
+{
+ return ((rtems_get_processor_count() + 1) / 2);
+}
+
+static void
+test_mtx_body(rtems_test_parallel_context *base, void *arg,
+ size_t active_workers, size_t worker_index)
+{
+ test_context *ctx = (test_context *)base;
+ uint32_t obj_count = get_obj_count();
+ uint32_t r = worker_index;
+
+ while (!rtems_test_parallel_stop_job(&ctx->base)) {
+ uint32_t op = (r >> 17) % 2;
+ uint32_t i = (r >> 7) % obj_count;
+ struct mtx *mtx = &ctx->mtx[i];
+ volatile uint32_t *value = &ctx->value[i];
+ bool locked;
+
+ switch (op) {
+ case 0:
+ locked = mtx_trylock(mtx) == 1;
+ if (locked) {
+ ++ctx->stats.mtx_try_success[i];
+ } else {
+ ++ctx->stats.mtx_try_failed[i];
+ }
+
+ break;
+ case 1:
+ mtx_lock(mtx);
+ ++ctx->stats.mtx_lock[i];
+ locked = true;
+ break;
+ }
+
+ if (locked) {
+ assert(*value == i);
+ *value = 0xdeadbeef;
+ busy();
+ *value = i;
+ mtx_unlock(mtx);
+ }
+
+ r = simple_random(r);
+ }
+}
+
+static void
+test_cv_body(rtems_test_parallel_context *base, void *arg,
+ size_t active_workers, size_t worker_index)
+{
+ test_context *ctx = (test_context *)base;
+ uint32_t obj_count = get_obj_count();
+ uint32_t r = worker_index;
+
+ while (!rtems_test_parallel_stop_job(&ctx->base)) {
+ uint32_t op = (r >> 17) % 3;
+ uint32_t i = (r >> 7) % obj_count;
+ struct mtx *mtx = &ctx->mtx[i];
+ struct cv *cv = &ctx->cv[i];
+
+ mtx_lock(mtx);
+
+ switch (op) {
+ case 0:
+ cv_signal(cv);
+ ++ctx->stats.cv_signal[i];
+ break;
+ case 1:
+ cv_broadcast(cv);
+ ++ctx->stats.cv_broadcast[i];
+ break;
+ case 2:
+ if (cv_timedwait(cv, mtx, 1) == 0) {
+ ++ctx->stats.cv_timedwait_success[i];
+ } else {
+ ++ctx->stats.cv_timedwait_timeout[i];
+ }
+
+ break;
+ }
+
+ mtx_unlock(mtx);
+
+ r = simple_random(r);
+ }
+}
+
+static const rtems_test_parallel_job test_jobs[] = {
+ {
+ .init = test_init,
+ .body = test_cv_body,
+ .fini = test_fini
+ }, {
+ .init = test_init,
+ .body = test_mtx_body,
+ .fini = test_fini
+ }
+};
+
+static void setup_worker(
+ rtems_test_parallel_context *base,
+ size_t worker_index,
+ rtems_id worker_id
+)
+{
+ rtems_task_priority prio;
+ rtems_status_code sc;
+
+ prio = ((worker_index - 1) % 2) + 253;
+ sc = rtems_task_set_priority(worker_id, prio, &prio);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+print_summary(const test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < get_obj_count(); ++i) {
+ printf("mtx lock[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.mtx_lock[i]);
+ printf("mtx try success[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.mtx_try_success[i]);
+ printf("mtx try failed[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.mtx_try_failed[i]);
+ }
+
+ for (i = 0; i < get_obj_count(); ++i) {
+ printf("cv signal[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.cv_signal[i]);
+ printf("cv broadcast[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.cv_broadcast[i]);
+ printf("cv wait success[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.cv_timedwait_success[i]);
+ printf("cv wait timeout[%zu]: %" PRIu32 "\n", i,
+ ctx->stats.cv_timedwait_timeout[i]);
+ }
+}
+
+static void
+test_main(void)
+{
+ test_context *ctx = &test_instance;
+ size_t i;
+ rtems_id id;
+ rtems_status_code sc;
+
+ for (i = 0; i < OBJ_COUNT; ++i) {
+ ctx->value[i] = i;
+ mtx_init(&ctx->mtx[i], "test", NULL, MTX_DEF);
+ cv_init(&ctx->cv[i], "test");
+ }
+
+ rtems_test_parallel(&ctx->base, setup_worker, &test_jobs[0],
+ RTEMS_ARRAY_SIZE(test_jobs));
+
+ print_summary(ctx);
+
+ for (i = 0; i < OBJ_COUNT; ++i) {
+ mtx_destroy(&ctx->mtx[i]);
+ cv_destroy(&ctx->cv[i]);
+ }
+
+ exit(0);
+}
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
+
+#include <rtems/bsd/test/default-init.h>