Changeset 57f125d in rtems


Ignore:
Timestamp:
Jan 2, 2013, 5:56:35 PM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
0b422d56
Parents:
69d034a
git-author:
Sebastian Huber <sebastian.huber@…> (01/02/13 17:56:35)
git-committer:
Sebastian Huber <sebastian.huber@…> (01/07/13 14:13:24)
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

    r69d034a r57f125d  
    5050       */
    5151      _ISR_Disable( level );
    52         #if defined(RTEMS_DEBUG)
    53           if ( !the_thread->Wait.count ) {  /* verify thread is waiting */
    54             _Thread_Unnest_dispatch();
    55             _ISR_Enable( level );
    56             return;
    57           }
    58         #endif
     52        /*
     53         * Verify that the thread is still waiting for the event condition.
     54         * This test is necessary to avoid state corruption if the timeout
     55         * happens after the event condition is satisfied in
     56         * _Event_Surrender().  A satisfied event condition is indicated with
     57         * count set to zero.
     58         */
     59        if ( !the_thread->Wait.count ) {
     60          _Thread_Unnest_dispatch();
     61          _ISR_Enable( level );
     62          return;
     63        }
    5964
    6065        the_thread->Wait.count = 0;
  • testsuites/sptests/spintrcritical10/init.c

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

    r69d034a r57f125d  
    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.