From 57f125d02595661b72d66f27b6f71c9b9579f516 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 2 Jan 2013 18:56:35 +0100 Subject: rtems: Critical fix for events Commit 4b45c1393ce4ee3e1c2762ef3145d2bd6b5b38da marked a test in _Event_Timeout() as debug only. This test is required also in non-debug configurations since otherwise state corruption can happen. A revised test sptests/spintrcritical10 checks the relevant sequences. --- testsuites/sptests/spintrcritical10/init.c | 307 +++++++++++++++++++-- .../sptests/spintrcritical10/spintrcritical10.scn | 5 +- 2 files changed, 289 insertions(+), 23 deletions(-) (limited to 'testsuites') diff --git a/testsuites/sptests/spintrcritical10/init.c b/testsuites/sptests/spintrcritical10/init.c index 66306cd966..f284780546 100644 --- a/testsuites/sptests/spintrcritical10/init.c +++ b/testsuites/sptests/spintrcritical10/init.c @@ -2,49 +2,316 @@ * COPYRIGHT (c) 1989-2012. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2013 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. */ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 #include #include -/* forward declarations to avoid warnings */ -rtems_task Init(rtems_task_argument argument); +#define GREEN RTEMS_EVENT_0 -rtems_id Main_task; +#define RED RTEMS_EVENT_1 -rtems_task Init( - rtems_task_argument ignored -) +#define EVENTS (GREEN | RED) + +#define DEADBEEF 0xdeadbeef + +typedef struct { + rtems_id timer; + Thread_Control *thread; + bool hit; +} test_context; + +static void any_satisfy_before_timeout(rtems_id timer, void *arg) { - rtems_status_code sc; - rtems_event_set out; - int resets; + rtems_status_code sc; + test_context *ctx = arg; + const Thread_Control *thread = ctx->thread; - puts( "\n\n*** TEST INTERRUPT CRITICAL SECTION 10 ***" ); + if (thread->Wait.count != 0) { + ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; + + rtems_test_assert(thread->Wait.count == EVENTS); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + sc = rtems_event_send(thread->Object.id, GREEN); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == GREEN + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + sc = rtems_event_send(thread->Object.id, RED); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == GREEN + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + _Event_Timeout(thread->Object.id, &_Event_Sync_state); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == GREEN + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + if (ctx->hit) { + rtems_test_assert( + _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED + ); + } + } + + sc = rtems_timer_reset(timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void test_any_satisfy_before_timeout(test_context *ctx) +{ + rtems_status_code sc; + int resets = 0; + + puts( + "Init - Trying to generate any satisfied before timeout " + "while blocking on event" + ); + + ctx->hit = false; + + interrupt_critical_section_test_support_initialize(NULL); + + sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + while (!ctx->hit && resets < 2) { + rtems_event_set out; + + if (interrupt_critical_section_test_support_delay()) + resets++; + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == GREEN); + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == RED); + } + + sc = rtems_timer_cancel(ctx->timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(ctx->hit); +} + +static void all_satisfy_before_timeout(rtems_id timer, void *arg) +{ + rtems_status_code sc; + test_context *ctx = arg; + const Thread_Control *thread = ctx->thread; + + if (thread->Wait.count != 0) { + ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; + + rtems_test_assert(thread->Wait.count == EVENTS); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + sc = rtems_event_send(thread->Object.id, GREEN); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(thread->Wait.count == EVENTS); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + sc = rtems_event_send(thread->Object.id, RED); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == EVENTS + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + _Event_Timeout(thread->Object.id, &_Event_Sync_state); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == EVENTS + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + if (ctx->hit) { + rtems_test_assert( + _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED + ); + } + } - puts( "Init - Test may not be able to detect case is hit reliably" ); - puts( "Init - Trying to generate timeout while blocking on event" ); + sc = rtems_timer_reset(timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void test_all_satisfy_before_timeout(test_context *ctx) +{ + rtems_status_code sc; + int resets = 0; + + puts( + "Init - Trying to generate all satisfied before timeout " + "while blocking on event" + ); + + ctx->hit = false; + + interrupt_critical_section_test_support_initialize(NULL); - Main_task = rtems_task_self(); + sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); - interrupt_critical_section_test_support_initialize( NULL ); + while (!ctx->hit && resets < 2) { + rtems_event_set out; - for (resets=0 ; resets< 2 ;) { - if ( interrupt_critical_section_test_support_delay() ) + if (interrupt_critical_section_test_support_delay()) resets++; - sc = rtems_event_receive( 0x01, RTEMS_DEFAULT_OPTIONS, 1, &out ); - fatal_directive_status( sc, RTEMS_TIMEOUT, "event_receive timeout" ); + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == EVENTS); } + sc = rtems_timer_cancel(ctx->timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(ctx->hit); +} + +static void timeout_before_satisfied(rtems_id timer, void *arg) +{ + rtems_status_code sc; + test_context *ctx = arg; + const Thread_Control *thread = ctx->thread; + + if (thread->Wait.count != 0) { + ctx->hit = + _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; + + rtems_test_assert(thread->Wait.count == EVENTS); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); + + _Event_Timeout(thread->Object.id, &_Event_Sync_state); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_TIMEOUT); + + sc = rtems_event_send(thread->Object.id, EVENTS); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(thread->Wait.count == 0); + rtems_test_assert( + *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF + ); + rtems_test_assert(thread->Wait.return_code == RTEMS_TIMEOUT); + + if (ctx->hit) { + rtems_test_assert( + _Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT + ); + } + } + + sc = rtems_timer_reset(timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void test_timeout_before_all_satisfy(test_context *ctx) +{ + rtems_status_code sc; + int resets = 0; + + puts( + "Init - Trying to generate timeout before all satisfied " + "while blocking on event" + ); + + ctx->hit = false; + + interrupt_critical_section_test_support_initialize(NULL); + + sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + while (!ctx->hit && resets < 2) { + rtems_event_set out; + + if (interrupt_critical_section_test_support_delay()) + resets++; + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_TIMEOUT); + rtems_test_assert(out == DEADBEEF); + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == EVENTS); + } + + sc = rtems_timer_cancel(ctx->timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(ctx->hit); +} + +static rtems_task Init( + rtems_task_argument ignored +) +{ + rtems_status_code sc; + test_context ctx = { + .thread = _Thread_Executing + }; + + puts( "\n\n*** TEST INTERRUPT CRITICAL SECTION 10 ***" ); + + sc = rtems_timer_create(rtems_build_name('T', 'I', 'M', 'R'), &ctx.timer); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + test_any_satisfy_before_timeout(&ctx); + test_all_satisfy_before_timeout(&ctx); + test_timeout_before_all_satisfy(&ctx); + puts( "*** END OF TEST INTERRUPT CRITICAL SECTION 10 ***" ); rtems_test_exit(0); } @@ -61,5 +328,3 @@ rtems_task Init( #define CONFIGURE_INIT #include - -/* global variables */ diff --git a/testsuites/sptests/spintrcritical10/spintrcritical10.scn b/testsuites/sptests/spintrcritical10/spintrcritical10.scn index 9f59c0ea4d..e8db0c576a 100644 --- a/testsuites/sptests/spintrcritical10/spintrcritical10.scn +++ b/testsuites/sptests/spintrcritical10/spintrcritical10.scn @@ -1,4 +1,5 @@ *** TEST INTERRUPT CRITICAL SECTION 10 *** -Init - Test may not be able to detect case is hit reliably -Init - Trying to generate timeout while blocking on event +Init - Trying to generate any satisfied before timeout while blocking on event +Init - Trying to generate all satisfied before timeout while blocking on event +Init - Trying to generate timeout before all satisfied while blocking on event *** END OF TEST INTERRUPT CRITICAL SECTION 10 *** -- cgit v1.2.3