Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:47

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  Classic API Signal to Task from ISR
0005  *
0006  *  Copyright (C) 2020 embedded brains GmbH & Co. KG
0007  *
0008  *  COPYRIGHT (c) 1989-2011.
0009  *  On-Line Applications Research Corporation (OAR).
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions
0013  * are met:
0014  * 1. Redistributions of source code must retain the above copyright
0015  *    notice, this list of conditions and the following disclaimer.
0016  * 2. Redistributions in binary form must reproduce the above copyright
0017  *    notice, this list of conditions and the following disclaimer in the
0018  *    documentation and/or other materials provided with the distribution.
0019  *
0020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0021  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0023  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0024  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0025  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0026  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0027  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0028  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0029  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0030  * POSSIBILITY OF SUCH DAMAGE.
0031  */
0032 
0033 #ifdef HAVE_CONFIG_H
0034 #include "config.h"
0035 #endif
0036 
0037 #include <rtems/test.h>
0038 #include <rtems/test-info.h>
0039 
0040 #include <rtems/score/threadimpl.h>
0041 #include <rtems/rtems/eventimpl.h>
0042 
0043 const char rtems_test_name[] = "SPINTRCRITICAL 21";
0044 
0045 #define MAX_ITERATION_COUNT 10000
0046 
0047 typedef struct {
0048   rtems_id        main_task;
0049   Thread_Control *main_thread;
0050   rtems_id        other_task;
0051 } test_context;
0052 
0053 static void clear_pending_events( void )
0054 {
0055   rtems_event_set out;
0056 
0057   (void) rtems_event_receive(
0058     RTEMS_ALL_EVENTS,
0059     RTEMS_NO_WAIT | RTEMS_EVENT_ANY,
0060     0,
0061     &out
0062   );
0063 }
0064 
0065 static bool is_blocked( Thread_Wait_flags flags )
0066 {
0067   return flags == ( THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_BLOCKED );
0068 }
0069 
0070 static bool interrupts_blocking_op( Thread_Wait_flags flags )
0071 {
0072   return flags
0073     == ( THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK );
0074 }
0075 
0076 static T_interrupt_test_state event_from_isr_interrupt(
0077   void *arg
0078 )
0079 {
0080   test_context           *ctx;
0081   T_interrupt_test_state state;
0082   Thread_Wait_flags      flags;
0083   rtems_status_code      status;
0084 
0085   ctx = arg;
0086   flags = _Thread_Wait_flags_get( ctx->main_thread );
0087 
0088   if ( interrupts_blocking_op( flags ) ) {
0089     /*
0090      *  This event send hits the critical section but sends to
0091      *  another task so doesn't impact this critical section.
0092      */
0093     status = rtems_event_send( ctx->other_task, 0x02 );
0094     T_quiet_rsc_success( status );
0095 
0096     /*
0097      *  This event send hits the main task but doesn't satisfy
0098      *  it's blocking condition so it will still block
0099      */
0100     status = rtems_event_send( ctx->main_task, 0x02 );
0101     T_quiet_rsc_success( status );
0102 
0103     state = T_INTERRUPT_TEST_DONE;
0104   } else if ( is_blocked( flags ) ) {
0105     state = T_INTERRUPT_TEST_LATE;
0106   } else {
0107     state = T_INTERRUPT_TEST_EARLY;
0108   }
0109 
0110   status = rtems_event_send( ctx->main_task, 0x01 );
0111   T_quiet_rsc_success( status );
0112 
0113   return state;
0114 }
0115 
0116 static void event_from_isr_action( void *arg )
0117 {
0118   rtems_status_code status;
0119   rtems_event_set   out;
0120 
0121   (void) arg;
0122 
0123   status = rtems_event_receive( 0x01, RTEMS_DEFAULT_OPTIONS, 0, &out );
0124   T_quiet_rsc_success( status );
0125 }
0126 
0127 static const T_interrupt_test_config event_from_isr_config = {
0128   .action = event_from_isr_action,
0129   .interrupt = event_from_isr_interrupt,
0130   .max_iteration_count = MAX_ITERATION_COUNT
0131 };
0132 
0133 T_TEST_CASE(EventFromISR)
0134 {
0135   test_context           ctx;
0136   T_interrupt_test_state state;
0137   rtems_status_code      status;
0138 
0139   ctx.main_task = rtems_task_self();
0140   ctx.main_thread = _Thread_Get_executing();
0141 
0142   status = rtems_task_create(
0143     0xa5a5a5a5,
0144     1,
0145     RTEMS_MINIMUM_STACK_SIZE,
0146     RTEMS_DEFAULT_MODES,
0147     RTEMS_DEFAULT_ATTRIBUTES,
0148     &ctx.other_task
0149   );
0150   T_assert_rsc_success( status );
0151 
0152   state = T_interrupt_test( &event_from_isr_config, &ctx );
0153   T_eq_int( state, T_INTERRUPT_TEST_DONE );
0154 
0155   status = rtems_task_delete( ctx.other_task );
0156   T_rsc_success( status );
0157 
0158   clear_pending_events();
0159 }
0160 
0161 static T_interrupt_test_state event_with_timeout_from_isr_interrupt(
0162   void *arg
0163 )
0164 {
0165   test_context           *ctx;
0166   T_interrupt_test_state  state;
0167   Thread_Wait_flags       flags;
0168   rtems_status_code       status;
0169 
0170   ctx = arg;
0171   flags = _Thread_Wait_flags_get( ctx->main_thread );
0172 
0173   if ( interrupts_blocking_op( flags ) ) {
0174     /*
0175      *  We want to catch the task while it is blocking.  Otherwise
0176      *  just send and make it happy.
0177      */
0178     state = T_INTERRUPT_TEST_DONE;
0179   } else if ( is_blocked( flags ) ) {
0180     state = T_INTERRUPT_TEST_LATE;
0181   } else {
0182     state = T_INTERRUPT_TEST_EARLY;
0183   }
0184 
0185   status = rtems_event_send( ctx->main_task, 0x01 );
0186   T_quiet_rsc_success( status );
0187 
0188   return state;
0189 }
0190 
0191 static void event_with_timeout_from_isr_action( void *arg )
0192 {
0193   rtems_status_code status;
0194   rtems_event_set   out;
0195 
0196   (void) arg;
0197 
0198   status = rtems_event_receive( 0x01, RTEMS_DEFAULT_OPTIONS, 1, &out );
0199   T_quiet_true( status == RTEMS_SUCCESSFUL || status == RTEMS_TIMEOUT );
0200 }
0201 
0202 static const T_interrupt_test_config event_with_timeout_from_isr_config = {
0203   .action = event_with_timeout_from_isr_action,
0204   .interrupt = event_with_timeout_from_isr_interrupt,
0205   .max_iteration_count = MAX_ITERATION_COUNT
0206 };
0207 
0208 T_TEST_CASE( EventWithTimeoutFromISR )
0209 {
0210   test_context           ctx;
0211   T_interrupt_test_state state;
0212 
0213   ctx.main_task = rtems_task_self();
0214   ctx.main_thread = _Thread_Get_executing();
0215   ctx.other_task = 0xdeadbeef;
0216 
0217   state = T_interrupt_test( &event_with_timeout_from_isr_config, &ctx );
0218   T_eq_int( state, T_INTERRUPT_TEST_DONE );
0219 
0220   clear_pending_events();
0221 }
0222 
0223 static rtems_task Init( rtems_task_argument argument )
0224 {
0225   rtems_test_run( argument, TEST_STATE );
0226 }
0227 
0228 #define CONFIGURE_INIT
0229 
0230 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0231 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0232 
0233 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0234 
0235 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0236 
0237 #define CONFIGURE_MICROSECONDS_PER_TICK   1000
0238 
0239 #define CONFIGURE_MAXIMUM_TASKS             2
0240 
0241 #include <rtems/confdefs.h>