Changeset 39691cd in rtems


Ignore:
Timestamp:
Jan 2, 2013, 5:56:35 PM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.10
Children:
8949e5b
Parents:
073e3e10
git-author:
Sebastian Huber <sebastian.huber@…> (01/02/13 17:56:35)
git-committer:
Sebastian Huber <sebastian.huber@…> (01/07/13 14:21:40)
Message:

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.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/rtems/src/eventtimeout.c

    r073e3e10 r39691cd  
    6565       */
    6666      _ISR_Disable( level );
    67         #if defined(RTEMS_DEBUG)
    68           if ( !the_thread->Wait.count ) {  /* verify thread is waiting */
    69             _Thread_Unnest_dispatch();
    70             _ISR_Enable( level );
    71             return;
    72           }
    73         #endif
     67        /*
     68         * Verify that the thread is still waiting for the event condition.
     69         * This test is necessary to avoid state corruption if the timeout
     70         * happens after the event condition is satisfied in
     71         * _Event_Surrender().  A satisfied event condition is indicated with
     72         * count set to zero.
     73         */
     74        if ( !the_thread->Wait.count ) {
     75          _Thread_Unnest_dispatch();
     76          _ISR_Enable( level );
     77          return;
     78        }
    7479
    7580        the_thread->Wait.count = 0;
  • testsuites/sptests/spintrcritical10/init.c

    r073e3e10 r39691cd  
    22 *  COPYRIGHT (c) 1989-2009.
    33 *  On-Line Applications Research Corporation (OAR).
     4 *
     5 *  Copyright (c) 2013 embedded brains GmbH.
    46 *
    57 *  The license and distribution terms for this file may be
     
    1012 */
    1113
     14#ifdef HAVE_CONFIG_H
     15  #include "config.h"
     16#endif
     17
    1218#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
    1319#include <tmacros.h>
    1420#include <intrcritical.h>
    1521
    16 rtems_id Main_task;
    17 
    18 rtems_task Init(
     22#define GREEN RTEMS_EVENT_0
     23
     24#define RED RTEMS_EVENT_1
     25
     26#define EVENTS (GREEN | RED)
     27
     28#define DEADBEEF 0xdeadbeef
     29
     30typedef struct {
     31  rtems_id timer;
     32  Thread_Control *thread;
     33  bool hit;
     34} test_context;
     35
     36static void any_satisfy_before_timeout(rtems_id timer, void *arg)
     37{
     38  rtems_status_code sc;
     39  test_context *ctx = arg;
     40  const Thread_Control *thread = ctx->thread;
     41
     42  if (thread->Wait.count != 0) {
     43    ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
     44
     45    rtems_test_assert(thread->Wait.count == EVENTS);
     46    rtems_test_assert(
     47      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     48    );
     49    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     50
     51    sc = rtems_event_send(thread->Object.id, GREEN);
     52    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     53
     54    rtems_test_assert(thread->Wait.count == 0);
     55    rtems_test_assert(
     56      *(rtems_event_set *) thread->Wait.return_argument == GREEN
     57    );
     58    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     59
     60    sc = rtems_event_send(thread->Object.id, RED);
     61    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     62
     63    rtems_test_assert(thread->Wait.count == 0);
     64    rtems_test_assert(
     65      *(rtems_event_set *) thread->Wait.return_argument == GREEN
     66    );
     67    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     68
     69    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
     70
     71    rtems_test_assert(thread->Wait.count == 0);
     72    rtems_test_assert(
     73      *(rtems_event_set *) thread->Wait.return_argument == GREEN
     74    );
     75    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     76
     77    if (ctx->hit) {
     78      rtems_test_assert(
     79        _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
     80      );
     81    }
     82  }
     83
     84  sc = rtems_timer_reset(timer);
     85  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     86}
     87
     88static void test_any_satisfy_before_timeout(test_context *ctx)
     89{
     90  rtems_status_code sc;
     91  int resets = 0;
     92
     93  puts(
     94    "Init - Trying to generate any satisfied before timeout "
     95    "while blocking on event"
     96  );
     97
     98  ctx->hit = false;
     99
     100  interrupt_critical_section_test_support_initialize(NULL);
     101
     102  sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx);
     103  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     104
     105  while (!ctx->hit && resets < 2) {
     106    rtems_event_set out;
     107
     108    if (interrupt_critical_section_test_support_delay())
     109      resets++;
     110
     111    out = DEADBEEF;
     112    sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out);
     113    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     114    rtems_test_assert(out == GREEN);
     115
     116    out = DEADBEEF;
     117    sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out);
     118    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     119    rtems_test_assert(out == RED);
     120  }
     121
     122  sc = rtems_timer_cancel(ctx->timer);
     123  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     124
     125  rtems_test_assert(ctx->hit);
     126}
     127
     128static void all_satisfy_before_timeout(rtems_id timer, void *arg)
     129{
     130  rtems_status_code sc;
     131  test_context *ctx = arg;
     132  const Thread_Control *thread = ctx->thread;
     133
     134  if (thread->Wait.count != 0) {
     135    ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
     136
     137    rtems_test_assert(thread->Wait.count == EVENTS);
     138    rtems_test_assert(
     139      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     140    );
     141    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     142
     143    sc = rtems_event_send(thread->Object.id, GREEN);
     144    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     145
     146    rtems_test_assert(thread->Wait.count == EVENTS);
     147    rtems_test_assert(
     148      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     149    );
     150    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     151
     152    sc = rtems_event_send(thread->Object.id, RED);
     153    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     154
     155    rtems_test_assert(thread->Wait.count == 0);
     156    rtems_test_assert(
     157      *(rtems_event_set *) thread->Wait.return_argument == EVENTS
     158    );
     159    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     160
     161    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
     162
     163    rtems_test_assert(thread->Wait.count == 0);
     164    rtems_test_assert(
     165      *(rtems_event_set *) thread->Wait.return_argument == EVENTS
     166    );
     167    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     168
     169    if (ctx->hit) {
     170      rtems_test_assert(
     171        _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
     172      );
     173    }
     174  }
     175
     176  sc = rtems_timer_reset(timer);
     177  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     178}
     179
     180static void test_all_satisfy_before_timeout(test_context *ctx)
     181{
     182  rtems_status_code sc;
     183  int resets = 0;
     184
     185  puts(
     186    "Init - Trying to generate all satisfied before timeout "
     187    "while blocking on event"
     188  );
     189
     190  ctx->hit = false;
     191
     192  interrupt_critical_section_test_support_initialize(NULL);
     193
     194  sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx);
     195  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     196
     197  while (!ctx->hit && resets < 2) {
     198    rtems_event_set out;
     199
     200    if (interrupt_critical_section_test_support_delay())
     201      resets++;
     202
     203    out = DEADBEEF;
     204    sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
     205    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     206    rtems_test_assert(out == EVENTS);
     207  }
     208
     209  sc = rtems_timer_cancel(ctx->timer);
     210  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     211
     212  rtems_test_assert(ctx->hit);
     213}
     214
     215static void timeout_before_satisfied(rtems_id timer, void *arg)
     216{
     217  rtems_status_code sc;
     218  test_context *ctx = arg;
     219  const Thread_Control *thread = ctx->thread;
     220
     221  if (thread->Wait.count != 0) {
     222    ctx->hit =
     223      _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
     224
     225    rtems_test_assert(thread->Wait.count == EVENTS);
     226    rtems_test_assert(
     227      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     228    );
     229    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
     230
     231    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
     232
     233    rtems_test_assert(thread->Wait.count == 0);
     234    rtems_test_assert(
     235      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     236    );
     237    rtems_test_assert(thread->Wait.return_code == RTEMS_TIMEOUT);
     238
     239    sc = rtems_event_send(thread->Object.id, EVENTS);
     240    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     241
     242    rtems_test_assert(thread->Wait.count == 0);
     243    rtems_test_assert(
     244      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     245    );
     246    rtems_test_assert(thread->Wait.return_code == RTEMS_TIMEOUT);
     247
     248    if (ctx->hit) {
     249      rtems_test_assert(
     250        _Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT
     251      );
     252    }
     253  }
     254
     255  sc = rtems_timer_reset(timer);
     256  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     257}
     258
     259static void test_timeout_before_all_satisfy(test_context *ctx)
     260{
     261  rtems_status_code sc;
     262  int resets = 0;
     263
     264  puts(
     265    "Init - Trying to generate timeout before all satisfied "
     266    "while blocking on event"
     267  );
     268
     269  ctx->hit = false;
     270
     271  interrupt_critical_section_test_support_initialize(NULL);
     272
     273  sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx);
     274  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     275
     276  while (!ctx->hit && resets < 2) {
     277    rtems_event_set out;
     278
     279    if (interrupt_critical_section_test_support_delay())
     280      resets++;
     281
     282    out = DEADBEEF;
     283    sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
     284    rtems_test_assert(sc == RTEMS_TIMEOUT);
     285    rtems_test_assert(out == DEADBEEF);
     286
     287    out = DEADBEEF;
     288    sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out);
     289    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     290    rtems_test_assert(out == EVENTS);
     291  }
     292
     293  sc = rtems_timer_cancel(ctx->timer);
     294  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     295
     296  rtems_test_assert(ctx->hit);
     297}
     298
     299static rtems_task Init(
    19300  rtems_task_argument ignored
    20301)
    21302{
    22   rtems_status_code     sc;
    23   rtems_event_set       out;
    24   int                   resets;
     303  rtems_status_code sc;
     304  test_context ctx = {
     305    .thread = _Thread_Executing
     306  };
    25307
    26308  puts( "\n\n*** TEST INTERRUPT CRITICAL SECTION 10 ***" );
    27309
    28   puts( "Init - Test may not be able to detect case is hit reliably" );
    29   puts( "Init - Trying to generate timeout while blocking on event" );
    30 
    31   Main_task = rtems_task_self();
    32 
    33   interrupt_critical_section_test_support_initialize( NULL );
    34 
    35   for (resets=0 ; resets< 2 ;) {
    36     if ( interrupt_critical_section_test_support_delay() )
    37       resets++;
    38 
    39     sc = rtems_event_receive( 0x01, RTEMS_DEFAULT_OPTIONS, 1, &out );
    40     fatal_directive_status( sc, RTEMS_TIMEOUT, "event_receive timeout" );
    41   }
     310  sc = rtems_timer_create(rtems_build_name('T', 'I', 'M', 'R'), &ctx.timer);
     311  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     312
     313  test_any_satisfy_before_timeout(&ctx);
     314  test_all_satisfy_before_timeout(&ctx);
     315  test_timeout_before_all_satisfy(&ctx);
    42316
    43317  puts( "*** END OF TEST INTERRUPT CRITICAL SECTION 10 ***" );
     
    57331#define CONFIGURE_INIT
    58332#include <rtems/confdefs.h>
    59 
    60 /* global variables */
  • testsuites/sptests/spintrcritical10/spintrcritical10.scn

    r073e3e10 r39691cd  
    11*** TEST INTERRUPT CRITICAL SECTION 10 ***
    2 Init - Test may not be able to detect case is hit reliably
    3 Init - Trying to generate timeout while blocking on event
     2Init - Trying to generate any satisfied before timeout while blocking on event
     3Init - Trying to generate all satisfied before timeout while blocking on event
     4Init - Trying to generate timeout before all satisfied while blocking on event
    45*** END OF TEST INTERRUPT CRITICAL SECTION 10 ***
Note: See TracChangeset for help on using the changeset viewer.