summaryrefslogblamecommitdiffstats
path: root/testsuites/sptests/sp35/priinv.c
blob: cc3415140d97e2fb004b0b0fdb20586910c9959f (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                       

                                                           
                                         

























                                                                      








                                                                         

                      



                    



                    

                                   

                                       



                                       

                             
                                 
                                             











                                                           
                            

                         
                                                      

                                  
                                                             
     
                  




                               
                                                     
       
                                                            
        
                                                        
                                                                 
                                       






                         
                       














                                                                             
                              


                                                   
                                                                            








                                    
                                                                          






                                                 
                                                                          











                                                                           
                                                                        







                                                
                                                                         













                                                                        
                                                                       







                                                       
     
                   
      
                                        
 







                                                                    
























                                                              
                                                








                            
 













                                                                              


                                                                      


                                                          
                 
              
     






                            
 












                                                                               


                                                                      










                                                                           
                           
                         
                             

        
 
               




                                                                            



                                   



                                                              
 
                                                                     
 











                                                                      
                                                                        












                                                                       
                                                                          
 





                                                                               
 




                                              
                                                            

                                                                   
                                                                       





                                                                               
                                                                          




                              



                                                          
                                                     

                                                                 
                                                                     





                                                                             
                                                          



                                                        
                                                  

                                                                 
                                                                     





                                                                             
                                                        



                                                       
                                                     

                                                                 
                                                                     





                                                                             
                                                            




                                                                     
                    



                               
                                                         
                                                
 

                                                                 

                                        
                                                                  



                                       


                           
/*
 *  Simple test program to demonstrate priority inversion when blocking
 *
   -Ulf Ivraeus ------------- --- -- -  -   -
 *  Saab Ericsson Space AB
 *  phone:  +46 (0)31 735 4542
 *  e-mail: ulf.ivraeus@space.se
 *  ----------------------------- --- -- -  -   -
 *
 *  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.
 */

/********************************************************************

  Semaphore Ids:
    Sync Mutex Id   = 0x18010009
    Local Mutex Id  = 0x1801000a
    Remote Mutex Id = 0x1801000b

  Task Ids:
    TaMedium[0] Id  = 0x08010002
    TaMedium[1] Id  = 0x08010003
    TaMedium[2] Id  = 0x08010004
    TaHigh Id       = 0x08010005
    TaLow Id        = 0x08010006
    TaHwSim Id      = 0x08010007

********************************************************************/

/********************************************************************/
/* define this to use the RTEMS 4.5 scheme for object names */
/* #define TEST_ON_RTEMS_45 */

/* define this to print the Id of the calling task */
/* #define TEST_ON_TASK_ID */

/* define this if you are (1) on a ERC32 and (2) want a SW ISR trigger */
#if defined(__sparc__)
/* #define TEST_USE_ISR */
#endif

/* define this if you want the test to exit */
#define TEST_EXIT_AFTER_ITERATIONS 10
/********************************************************************/

#define CONFIGURE_INIT

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <bsp.h>
#include <stdio.h>
#include "tmacros.h"

#include <rtems/score/threadimpl.h>

const char rtems_test_name[] = "SP 35";

#if defined(TEST_EXIT_AFTER_ITERATIONS)
volatile uint32_t Iterations = 0;
#endif

const char *CallerName(void);

/* Task entry point prototypes */
rtems_task Init(rtems_task_argument ignored);
rtems_task Medium_Exec(rtems_task_argument TaskArg);
rtems_task Low_Exec(rtems_task_argument TaskArg);
rtems_task High_Exec(rtems_task_argument TaskArg);
rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg);

/* ISR that signals that HW has completed */
rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector);

/* Test driver functions */
void AccessLocalHw(void);
void AccessRemoteHw(void);

const char *CallerName(void)
{
  static char buffer[32];
  Thread_Control *executing = _Thread_Get_executing();
#if defined(TEST_PRINT_TASK_ID)
  sprintf( buffer, "0x%08x -- %d",
      rtems_task_self(), _Thread_Get_priority( executing ) );
#else
  volatile union {
    uint32_t u;
    unsigned char c[4];
  } TempName;

  #if defined(TEST_ON_RTEMS_45)
    TempName.u = *(uint32_t *)executing->Object.name;
  #else
    TempName.u = (uint32_t) executing->Object.name.name_u32;
  #endif
  sprintf( buffer, "%c%c%c%c -- %" PRIdPriority_Control,
      TempName.c[0], TempName.c[1], TempName.c[2], TempName.c[3],
      _Thread_Get_priority( executing )
  );
#endif
  return buffer;
}

#define NofMediumTask_C 3

/* RTEMS identifiers */
rtems_id  TaMedium[NofMediumTask_C]; /* Medium-prio tasks accessing */
                                     /*    the common local HW */
rtems_id  TaHwSim;                   /* HW simulator */
rtems_id  TaLow;                     /* Low-prio task accessing common */
                                     /*    remote HW */
rtems_id  TaHigh;                    /* High-prio task accessing common */
                                     /*    remote HW */


rtems_id  LocalHwSync_S;             /* Syncrhonize task to local HW */
rtems_id  LocalHwAccess_R;           /* Execlusive access to the local HW */
rtems_id  RemoteHwAccess_R;          /* Execlusive access to the remote HW */


/* The following variable triggers simulated HW activity */
volatile bool StartHw = false;

rtems_task Medium_Exec(rtems_task_argument TaskArg)
{
  printf("Medium_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);

  rtems_task_wake_after(50);

  while(1) {
    AccessLocalHw();
  }

  /* JRS - task does not get here */

  printf("Medium_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
  while(1) {
    rtems_task_wake_after(10000);
  }
}

rtems_task High_Exec(rtems_task_argument TaskArg)
{
  printf("High_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);

  /* Delay more than the Low-prio task so that Remote HW access resource is
   * taken before call to AccesRemoteHw.
   */
  rtems_task_wake_after(250);

  while(1) {
    AccessRemoteHw();
  }

  /* JRS - task does not get here */

  printf("High_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
  while(1) {
    rtems_task_wake_after(10000);
  }
  /* task does not get here */
}

rtems_task Low_Exec(rtems_task_argument TaskArg)
{
  printf("Low_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);

  /* Delay less than High-prio task so that we take the remote HW access
   * resource before it does it. However, delay longer than the mid-prio
   * tasks so that we know for certain that they have taken control over
   * the local HW access.
   */
  rtems_task_wake_after(100);

  while(1) {
    AccessRemoteHw();
  }

  /* JRS - task does not get here */

  printf("Low_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
  while(1) {
    rtems_task_wake_after(10000);
  }
}


rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg)
{
#if 0
  int ISRCount = 0;
#endif
  printf("LocalHwSim_Exec begins...\n");

  while(1) {
    if (StartHw) {
      /* A test task has activated the HW, wait for a while and then
       * generate an interrupt
       */
      rtems_task_wake_after(100);

      StartHw = FALSE;
#if defined(TEST_USE_ISR)
      __asm__ volatile ("ta 5");
      __asm__ volatile ("nop");
      __asm__ volatile ("nop");
#else
      LocalHwIsr( 0x85 );
#endif
    }

  }

  printf("LocalHwSim_Exec ends...\n");
  while(1) {
    rtems_task_wake_after(10000);
  }
}


rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector)
{
  rtems_status_code status;

  /* Signal synchroniztion semaphore to invoke waiting task */
  status = rtems_semaphore_release(LocalHwSync_S);
  if (status != RTEMS_SUCCESSFUL) {
    printf( "LocalHwISR release %d\n", status );
    while(1); /* Error */
  }

  return;
}

void AccessLocalHw(void)
{
  rtems_status_code     Sts;

  printf("  AccessLocalHw called by %s\n", CallerName());

  /* Obtain exclusive access to local HW, Start HW, Wait for completion,
   * Release access
   */

  Sts = rtems_semaphore_obtain(LocalHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
  directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );

  StartHw = TRUE;

  Sts = rtems_semaphore_obtain(LocalHwSync_S, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
  directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );

  Sts = rtems_semaphore_release(LocalHwAccess_R);
  directive_failed( Sts, "rtems_semaphore_release(LocalHwAccess_R)" );

  printf("  AccessLocalHw returns to %s\n", CallerName());
  #if defined(TEST_EXIT_AFTER_ITERATIONS)
    if ( ++Iterations == 10 ) {
      TEST_END();
      exit(0);
    }
  #endif
  return;
}

void AccessRemoteHw(void)
{
  rtems_status_code     Sts;

  printf("AccessRemoteHw called by %s\n", CallerName());

  /* Obtain exclusive access to remote HW, Start HW, Wait for completion,
   * Release access
   */

  Sts = rtems_semaphore_obtain(RemoteHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
  directive_failed( Sts, "rtems_semaphore_obtain(RemoteHwAccess_R...)" );

  /* Carry out the remote access via the Local HW interface */
  printf("AccessRemoteHw access local %s\n", CallerName());
  AccessLocalHw();

  Sts = rtems_semaphore_release(RemoteHwAccess_R);
  directive_failed( Sts, "rtems_semaphore_release(RemoreHwAccess_R" );

  printf("AccessRemoteHw returns to %s\n", CallerName());
  return;
}

/*************************************************************************/
/**********************        INITIALIZATION        *********************/
/*************************************************************************/

/* The Init operation (the Init-task) */
rtems_task Init(rtems_task_argument ignored)
{
  rtems_status_code status;
#if defined(TEST_USE_ISR)
  rtems_isr_entry   DummyIsr;
#endif
  int i;

  TEST_BEGIN();

  /* Create synchronisation semaphore for LocalHwIsr -> Test Tasks */
  status = rtems_semaphore_create(
    rtems_build_name ('S', 'Y', 'N', 'C'),           /* name */
    0,                                               /* initial count = 0 */
    RTEMS_LOCAL                   |
    RTEMS_SIMPLE_BINARY_SEMAPHORE |
    RTEMS_NO_INHERIT_PRIORITY     |
    RTEMS_NO_PRIORITY_CEILING     |
    RTEMS_FIFO,
    0,
    &LocalHwSync_S);                                 /* *id */
  directive_failed( status, "rtems_semaphore_create (SYNC)" );

  printf( "Sync Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwSync_S );

  /* Create resource semaphore for exclusive access to the local HW */
  status = rtems_semaphore_create(
    rtems_build_name ('R', 'E', 'S', '1'), /* name             */
    1,                                     /* count            */
    RTEMS_PRIORITY         |
    RTEMS_BINARY_SEMAPHORE |
    RTEMS_INHERIT_PRIORITY |
    RTEMS_LOCAL,                           /* attribute_set    */
    1, /* insignificant */                 /* priority_ceiling */
    &LocalHwAccess_R);                     /* *id              */
  directive_failed( status, "rtems_semaphore_create (RES1)" );

  printf( "Local Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwAccess_R );

  /* Create resource semaphore for exclusive access to the remote HW */
  status = rtems_semaphore_create(
    rtems_build_name ('R', 'E', 'S', '2'), /* name             */
    1,                                     /* count            */
    RTEMS_PRIORITY         |
    RTEMS_BINARY_SEMAPHORE |
    RTEMS_INHERIT_PRIORITY |
    RTEMS_LOCAL,                           /* attribute_set    */
    1, /* insignificant */                 /* priority_ceiling */
    &RemoteHwAccess_R);                    /* *id              */
  directive_failed( status, "rtems_semaphore_create (RES2)" );

  printf( "Remote Mutex Id = 0x%08" PRIxrtems_id "\n", RemoteHwAccess_R );

#if defined(TEST_USE_ISR)
  /* Install ISR for HW/SW synchronization, use ta 0x85 which is synchronous */
  status = rtems_interrupt_catch(LocalHwIsr, 0x85 + 0x100, &DummyIsr);
  directive_failed( status, "rtems_interrupt_catch" );
#endif


  printf("Ending Init-task\n");
  /* Create and start all tasks in the test */

  /* -- Medium-prio Test Tasks --- */
  for (i = 0; i < NofMediumTask_C; i++) {
#define MEDIUM_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u) + 1u)
    status = rtems_task_create(
      rtems_build_name('M','E','D','0'+i),               /* Name */
      MEDIUM_PRIORITY,                                   /* Priority */
      RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
      RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
      &TaMedium[i]);                                     /* Assigned ID */
    directive_failed( status, "rtems_task_create (MEDn)" );

    printf( "TaMedium[%d] Id = 0x%08" PRIxrtems_id "\n", i, TaMedium[i] );
    status = rtems_task_start(
      TaMedium[i],
      Medium_Exec,
      (rtems_task_argument) i
    );
    directive_failed( status, "rtems_task_start (MEDn)" );
  }

  /* -- High-prio Test Task --- */
#define HIGH_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u))
  status = rtems_task_create(
    rtems_build_name('H','I','G','H'),                 /* Name */
    HIGH_PRIORITY,                                     /* Priority */
    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
    &TaHigh);                                          /* Assigned ID */
  directive_failed( status, "rtems_task_create (HIGH)" );

  printf( "TaHigh Id = 0x%08" PRIxrtems_id "\n", TaHigh );
  status = rtems_task_start(TaHigh, High_Exec, 0);
  directive_failed( status, "rtems_task_start (HIGH)" );

  /* -- Low-prio Test Task --- */
#define LOW_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 1u)
  status = rtems_task_create(
    rtems_build_name('L','O','W',' '),                 /* Name */
    LOW_PRIORITY,                                      /* Priority */
    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
    &TaLow);                                           /* Assigned ID */
  directive_failed( status, "rtems_task_create (LOW)" );

  printf( "TaLow Id = 0x%08" PRIxrtems_id "\n", TaLow );
  status = rtems_task_start(TaLow, Low_Exec, 0);
  directive_failed( status, "rtems_task_start (LOW)" );

  /* -- HW Simulator Task --- */
#define HWTASK_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 2u)
  status = rtems_task_create(
    rtems_build_name('H','W','S','M'),                 /* Name */
    HWTASK_PRIORITY,                                   /* Priority */
    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
    &TaHwSim);                                         /* Assigned ID */
  directive_failed( status, "rtems_task_create (HWSM)" );

  printf( "TaHwSim Id = 0x%08" PRIxrtems_id "\n", TaHwSim );

  status = rtems_task_start(TaHwSim, LocalHwSim_Exec, 0);
  directive_failed( status, "rtems_task_start (HWSM)" );

  /* Destroy the Init task (and let the ready tasks start running) */
  rtems_task_exit();
}

/* configuration information */

#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER

#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_EXTRA_TASK_STACKS (RTEMS_MINIMUM_STACK_SIZE * 3)

#define CONFIGURE_MAXIMUM_TASKS 10
#define CONFIGURE_MAXIMUM_SEMAPHORES 10

#include <rtems/confdefs.h>

/* end of file */