From a5c1b2be0cb6e451a558e5d944551dbc66aaff1f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 11 May 2016 17:52:13 +0200 Subject: score: Test thread priority queue disciplines Add test sptests/spmutex01, since no existing uni-processor test covered the thread priority queueing discipline for CORE mutexes. --- testsuites/sptests/spmutex01/Makefile.am | 19 ++ testsuites/sptests/spmutex01/init.c | 269 +++++++++++++++++++++++++++++ testsuites/sptests/spmutex01/spmutex01.doc | 14 ++ testsuites/sptests/spmutex01/spmutex01.scn | 2 + 4 files changed, 304 insertions(+) create mode 100644 testsuites/sptests/spmutex01/Makefile.am create mode 100644 testsuites/sptests/spmutex01/init.c create mode 100644 testsuites/sptests/spmutex01/spmutex01.doc create mode 100644 testsuites/sptests/spmutex01/spmutex01.scn diff --git a/testsuites/sptests/spmutex01/Makefile.am b/testsuites/sptests/spmutex01/Makefile.am new file mode 100644 index 0000000000..d3101a6c15 --- /dev/null +++ b/testsuites/sptests/spmutex01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = spmutex01 +spmutex01_SOURCES = init.c + +dist_rtems_tests_DATA = spmutex01.scn spmutex01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(spmutex01_OBJECTS) +LINK_LIBS = $(spmutex01_LDLIBS) + +spmutex01$(EXEEXT): $(spmutex01_OBJECTS) $(spmutex01_DEPENDENCIES) + @rm -f spmutex01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spmutex01/init.c b/testsuites/sptests/spmutex01/init.c new file mode 100644 index 0000000000..76d62c0567 --- /dev/null +++ b/testsuites/sptests/spmutex01/init.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include "tmacros.h" + +const char rtems_test_name[] = "SPMUTEX 1"; + +#define TASK_COUNT 5 + +typedef enum { + REQ_WAKE_UP_MASTER = RTEMS_EVENT_0, + REQ_WAKE_UP_HELPER = RTEMS_EVENT_1, + REQ_MTX_OBTAIN = RTEMS_EVENT_2, + REQ_MTX_RELEASE = RTEMS_EVENT_3 +} request_id; + +typedef enum { + A_1, + A_2_0, + A_2_1, + M, + H, + NONE +} task_id; + +typedef struct { + rtems_id mtx; + rtems_id tasks[TASK_COUNT]; + int generation[TASK_COUNT]; + int expected_generation[TASK_COUNT]; +} test_context; + +static test_context test_instance; + +static void start_task( + test_context *ctx, + task_id id, + rtems_task_entry entry, + rtems_task_priority prio +) +{ + rtems_status_code sc; + + sc = rtems_task_create( + rtems_build_name('T', 'A', 'S', 'K'), + prio, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &ctx->tasks[id] + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(ctx->tasks[id], entry, id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void send_event(test_context *ctx, task_id id, rtems_event_set events) +{ + rtems_status_code sc; + + sc = rtems_event_send(ctx->tasks[id], events); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static rtems_event_set wait_for_events(void) +{ + rtems_event_set events; + rtems_status_code sc; + + sc = rtems_event_receive( + RTEMS_ALL_EVENTS, + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &events + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + return events; +} + +static void sync_with_helper(test_context *ctx) +{ + rtems_event_set events; + + send_event(ctx, H, REQ_WAKE_UP_HELPER); + events = wait_for_events(); + rtems_test_assert(events == REQ_WAKE_UP_MASTER); +} + +static void request(test_context *ctx, task_id id, request_id req) +{ + send_event(ctx, id, req); + sync_with_helper(ctx); +} + +static void obtain(test_context *ctx) +{ + rtems_status_code sc; + + sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void release(test_context *ctx) +{ + rtems_status_code sc; + + sc = rtems_semaphore_release(ctx->mtx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void check_generations(test_context *ctx, task_id a, task_id b) +{ + size_t i; + + if (a != NONE) { + ++ctx->expected_generation[a]; + } + + if (b != NONE) { + ++ctx->expected_generation[b]; + } + + for (i = 0; i < TASK_COUNT; ++i) { + rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]); + } +} + +static void assert_prio( + test_context *ctx, + task_id id, + rtems_task_priority expected +) +{ + rtems_task_priority actual; + rtems_status_code sc; + + sc = rtems_task_set_priority( + ctx->tasks[id], + RTEMS_CURRENT_PRIORITY, + &actual + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(expected == actual); +} + +static void helper(rtems_task_argument arg) +{ + test_context *ctx = &test_instance; + + while (true) { + rtems_event_set events = wait_for_events(); + rtems_test_assert(events == REQ_WAKE_UP_HELPER); + send_event(ctx, M, REQ_WAKE_UP_MASTER); + } +} + +static void worker(rtems_task_argument arg) +{ + test_context *ctx = &test_instance; + task_id id = arg; + + while (true) { + rtems_event_set events = wait_for_events(); + + if ((events & REQ_MTX_OBTAIN) != 0) { + obtain(ctx); + ++ctx->generation[id]; + } + + if ((events & REQ_MTX_RELEASE) != 0) { + release(ctx); + ++ctx->generation[id]; + } + } +} + +static void test(void) +{ + test_context *ctx = &test_instance; + rtems_status_code sc; + + ctx->tasks[M] = rtems_task_self(); + start_task(ctx, A_1, worker, 1); + start_task(ctx, A_2_0, worker, 2); + start_task(ctx, A_2_1, worker, 2); + start_task(ctx, H, helper, 3); + + sc = rtems_semaphore_create( + rtems_build_name(' ', 'M', 'T', 'X'), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, + 0, + &ctx->mtx + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + obtain(ctx); + request(ctx, A_1, REQ_MTX_OBTAIN); + check_generations(ctx, NONE, NONE); + assert_prio(ctx, M, 1); + release(ctx); + check_generations(ctx, A_1, NONE); + assert_prio(ctx, M, 3); + request(ctx, A_1, REQ_MTX_RELEASE); + check_generations(ctx, A_1, NONE); + + obtain(ctx); + request(ctx, A_2_0, REQ_MTX_OBTAIN); + request(ctx, A_1, REQ_MTX_OBTAIN); + request(ctx, A_2_1, REQ_MTX_OBTAIN); + check_generations(ctx, NONE, NONE); + assert_prio(ctx, M, 1); + release(ctx); + check_generations(ctx, A_1, NONE); + assert_prio(ctx, M, 3); + assert_prio(ctx, A_1, 1); + request(ctx, A_1, REQ_MTX_RELEASE); + check_generations(ctx, A_1, A_2_0); + request(ctx, A_2_0, REQ_MTX_RELEASE); + check_generations(ctx, A_2_0, A_2_1); + request(ctx, A_2_1, REQ_MTX_RELEASE); + check_generations(ctx, A_2_1, NONE); +} + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + test(); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT + +#define CONFIGURE_MAXIMUM_SEMAPHORES 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_INIT_TASK_PRIORITY 3 + +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/sptests/spmutex01/spmutex01.doc b/testsuites/sptests/spmutex01/spmutex01.doc new file mode 100644 index 0000000000..7951024cf6 --- /dev/null +++ b/testsuites/sptests/spmutex01/spmutex01.doc @@ -0,0 +1,14 @@ +This file describes the directives and concepts tested by this test set. + +test set name: spmutex01 + +directives: + + - rtems_semaphore_create() + - rtems_semaphore_obtain() + - rtems_semaphore_release() + +concepts: + + - Ensure that priority inheritance mechanism works. + - Ensure that thread priority queueing discipline works. diff --git a/testsuites/sptests/spmutex01/spmutex01.scn b/testsuites/sptests/spmutex01/spmutex01.scn new file mode 100644 index 0000000000..9c85619baa --- /dev/null +++ b/testsuites/sptests/spmutex01/spmutex01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST SPMUTEX 1 *** +*** END OF TEST SPMUTEX 1 *** -- cgit v1.2.3