diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-11 17:52:13 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-12 13:20:33 +0200 |
commit | 9276fdec2ec381e455e81f0fe3175d574579f631 (patch) | |
tree | d6efd1c75e93575a24b5125cb126140e411284e6 | |
parent | Revert "score: Avoid use of uninitialized variable" (diff) | |
download | rtems-9276fdec2ec381e455e81f0fe3175d574579f631.tar.bz2 |
score: Fix CORE mutex initialization
The priority inheritance and ceiling CORE mutexes wrongly used the FIFO
queueing discipline. Delete misleading _CORE_mutex_Is_priority(). Bug
introduced by 1e1a91ed11458ddbb27b94d0001d8f0fc2ef7a97.
Add test sptests/spmutex01, since no existing uni-processor test covered
the thread priority queueing discipline for CORE mutexes.
-rw-r--r-- | cpukit/score/include/rtems/score/coremuteximpl.h | 19 | ||||
-rw-r--r-- | cpukit/score/src/coremutex.c | 6 | ||||
-rw-r--r-- | testsuites/sptests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/sptests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/sptests/spmutex01/Makefile.am | 19 | ||||
-rw-r--r-- | testsuites/sptests/spmutex01/init.c | 269 | ||||
-rw-r--r-- | testsuites/sptests/spmutex01/spmutex01.doc | 14 | ||||
-rw-r--r-- | testsuites/sptests/spmutex01/spmutex01.scn | 2 |
8 files changed, 309 insertions, 22 deletions
diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h index ef116ec7b8..34a9972c9e 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -460,25 +460,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_fifo( return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_FIFO; } -/** - * @brief Doex core mutex use priority blocking. - * - * This routine returns true if the mutex's wait discipline is PRIORITY and - * false otherwise. - * - * @param[in] the_attribute is the attribute set of the mutex. - * - * @retval true The mutex is using priority blocking order. - * @retval false The mutex is not using priority blocking order. - * - */ -RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_priority( - const CORE_mutex_Attributes *the_attribute -) -{ - return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY; -} - /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c index 8fc3a406d9..ea5e759dc4 100644 --- a/cpukit/score/src/coremutex.c +++ b/cpukit/score/src/coremutex.c @@ -82,10 +82,10 @@ CORE_mutex_Status _CORE_mutex_Initialize( _Thread_queue_Initialize( &the_mutex->Wait_queue ); - if ( _CORE_mutex_Is_priority( the_mutex_attributes ) ) { - the_mutex->operations = &_Thread_queue_Operations_priority; - } else { + if ( _CORE_mutex_Is_fifo( the_mutex_attributes ) ) { the_mutex->operations = &_Thread_queue_Operations_FIFO; + } else { + the_mutex->operations = &_Thread_queue_Operations_priority; } return CORE_MUTEX_STATUS_SUCCESSFUL; diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index ed8e759e87..20ea9d5cc5 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -33,6 +33,7 @@ _SUBDIRS = \ spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \ spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \ sptask_err04 spclock_err01 +_SUBDIRS += spmutex01 _SUBDIRS += spextensions01 _SUBDIRS += spsysinit01 if HAS_SMP diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index 593b65b8cb..c96edd3c43 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -46,6 +46,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +spmutex01/Makefile spextensions01/Makefile sptimerserver01/Makefile spsysinit01/Makefile 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 + * <rtems@embedded-brains.de> + * + * 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 <rtems/confdefs.h> 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 *** |