semtest.c File Reference

#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "semtest.h"

Go to the source code of this file.

Data Structures

struct  SEMAPHORE_PARAMETERS

Defines

#define semtstBLOCKING_EXPECTED_VALUE   ( ( unsigned long ) 0xfff )
#define semtstDELAY_FACTOR   ( ( portTickType ) 10 )
#define semtstNON_BLOCKING_EXPECTED_VALUE   ( ( unsigned long ) 0xff )
#define semtstNUM_TASKS   ( 4 )
#define semtstSTACK_SIZE   configMINIMAL_STACK_SIZE

Typedefs

typedef struct SEMAPHORE_PARAMETERS xSemaphoreParameters

Functions

static portTASK_FUNCTION (prvSemaphoreTest, pvParameters)
static portTASK_FUNCTION_PROTO (prvSemaphoreTest, pvParameters)
void vStartSemaphoreTasks (unsigned portBASE_TYPE uxPriority)
portBASE_TYPE xAreSemaphoreTasksStillRunning (void)

Variables

static volatile short sCheckVariables [semtstNUM_TASKS] = { 0 }
static volatile short sNextCheckVariable = 0


Define Documentation

#define semtstBLOCKING_EXPECTED_VALUE   ( ( unsigned long ) 0xfff )

Definition at line 89 of file semtest.c.

Referenced by portTASK_FUNCTION(), and vStartSemaphoreTasks().

#define semtstDELAY_FACTOR   ( ( portTickType ) 10 )

Definition at line 96 of file semtest.c.

Referenced by portTASK_FUNCTION().

#define semtstNON_BLOCKING_EXPECTED_VALUE   ( ( unsigned long ) 0xff )

Definition at line 90 of file semtest.c.

Referenced by portTASK_FUNCTION(), and vStartSemaphoreTasks().

#define semtstNUM_TASKS   ( 4 )

Definition at line 94 of file semtest.c.

Referenced by portTASK_FUNCTION(), and xAreSemaphoreTasksStillRunning().

#define semtstSTACK_SIZE   configMINIMAL_STACK_SIZE

Definition at line 92 of file semtest.c.

Referenced by vStartSemaphoreTasks().


Typedef Documentation


Function Documentation

static portTASK_FUNCTION ( prvSemaphoreTest  ,
pvParameters   
) [static]

Definition at line 174 of file semtest.c.

References pdFALSE, pdPASS, pdTRUE, portENTER_CRITICAL, portEXIT_CRITICAL, SEMAPHORE_PARAMETERS::pulSharedVariable, sCheckVariables, semtstBLOCKING_EXPECTED_VALUE, semtstDELAY_FACTOR, semtstNON_BLOCKING_EXPECTED_VALUE, semtstNUM_TASKS, sNextCheckVariable, taskYIELD, ulCounter, vTaskDelay(), SEMAPHORE_PARAMETERS::xBlockTime, SEMAPHORE_PARAMETERS::xSemaphore, xSemaphoreGive, and xSemaphoreTake.

00175 {
00176 xSemaphoreParameters *pxParameters;
00177 volatile unsigned long *pulSharedVariable, ulExpectedValue;
00178 unsigned long ulCounter;
00179 short sError = pdFALSE, sCheckVariableToUse;
00180 
00181     /* See which check variable to use.  sNextCheckVariable is not semaphore 
00182     protected! */
00183     portENTER_CRITICAL();
00184         sCheckVariableToUse = sNextCheckVariable;
00185         sNextCheckVariable++;
00186     portEXIT_CRITICAL();
00187 
00188     /* A structure is passed in as the parameter.  This contains the shared 
00189     variable being guarded. */
00190     pxParameters = ( xSemaphoreParameters * ) pvParameters;
00191     pulSharedVariable = pxParameters->pulSharedVariable;
00192 
00193     /* If we are blocking we use a much higher count to ensure loads of context
00194     switches occur during the count. */
00195     if( pxParameters->xBlockTime > ( portTickType ) 0 )
00196     {
00197         ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
00198     }
00199     else
00200     {
00201         ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE;
00202     }
00203 
00204     for( ;; )
00205     {
00206         /* Try to obtain the semaphore. */
00207         if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
00208         {
00209             /* We have the semaphore and so expect any other tasks using the
00210             shared variable to have left it in the state we expect to find
00211             it. */
00212             if( *pulSharedVariable != ulExpectedValue )
00213             {
00214                 sError = pdTRUE;
00215             }
00216             
00217             /* Clear the variable, then count it back up to the expected value
00218             before releasing the semaphore.  Would expect a context switch or
00219             two during this time. */
00220             for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
00221             {
00222                 *pulSharedVariable = ulCounter;
00223                 if( *pulSharedVariable != ulCounter )
00224                 {
00225                     sError = pdTRUE;
00226                 }
00227             }
00228 
00229             /* Release the semaphore, and if no errors have occurred increment the check
00230             variable. */
00231             if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
00232             {
00233                 sError = pdTRUE;
00234             }
00235 
00236             if( sError == pdFALSE )
00237             {
00238                 if( sCheckVariableToUse < semtstNUM_TASKS )
00239                 {
00240                     ( sCheckVariables[ sCheckVariableToUse ] )++;
00241                 }
00242             }
00243 
00244             /* If we have a block time then we are running at a priority higher
00245             than the idle priority.  This task takes a long time to complete
00246             a cycle (deliberately so to test the guarding) so will be starving
00247             out lower priority tasks.  Block for some time to allow give lower
00248             priority tasks some processor time. */
00249             vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
00250         }
00251         else
00252         {
00253             if( pxParameters->xBlockTime == ( portTickType ) 0 )
00254             {
00255                 /* We have not got the semaphore yet, so no point using the
00256                 processor.  We are not blocking when attempting to obtain the
00257                 semaphore. */
00258                 taskYIELD();
00259             }
00260         }
00261     }
00262 }

static portTASK_FUNCTION_PROTO ( prvSemaphoreTest  ,
pvParameters   
) [static]

void vStartSemaphoreTasks ( unsigned portBASE_TYPE  uxPriority  ) 

Definition at line 115 of file semtest.c.

References portTICK_RATE_MS, SEMAPHORE_PARAMETERS::pulSharedVariable, pvPortMalloc(), semtstBLOCKING_EXPECTED_VALUE, semtstNON_BLOCKING_EXPECTED_VALUE, semtstSTACK_SIZE, tskIDLE_PRIORITY, vQueueAddToRegistry, vSemaphoreCreateBinary, SEMAPHORE_PARAMETERS::xBlockTime, SEMAPHORE_PARAMETERS::xSemaphore, and xTaskCreate.

Referenced by main().

00116 {
00117 xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters;
00118 const portTickType xBlockTime = ( portTickType ) 100;
00119 
00120     /* Create the structure used to pass parameters to the first two tasks. */
00121     pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
00122 
00123     if( pxFirstSemaphoreParameters != NULL )
00124     {
00125         /* Create the semaphore used by the first two tasks. */
00126         vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore );
00127 
00128         if( pxFirstSemaphoreParameters->xSemaphore != NULL )
00129         {
00130             /* Create the variable which is to be shared by the first two tasks. */
00131             pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );
00132 
00133             /* Initialise the share variable to the value the tasks expect. */
00134             *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE;
00135 
00136             /* The first two tasks do not block on semaphore calls. */
00137             pxFirstSemaphoreParameters->xBlockTime = ( portTickType ) 0;
00138 
00139             /* Spawn the first two tasks.  As they poll they operate at the idle priority. */
00140             xTaskCreate( prvSemaphoreTest, ( signed char * ) "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
00141             xTaskCreate( prvSemaphoreTest, ( signed char * ) "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
00142         }
00143     }
00144 
00145     /* Do exactly the same to create the second set of tasks, only this time 
00146     provide a block time for the semaphore calls. */
00147     pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
00148     if( pxSecondSemaphoreParameters != NULL )
00149     {
00150         vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore );
00151 
00152         if( pxSecondSemaphoreParameters->xSemaphore != NULL )
00153         {
00154             pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );
00155             *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE;
00156             pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_RATE_MS;
00157 
00158             xTaskCreate( prvSemaphoreTest, ( signed char * ) "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL );
00159             xTaskCreate( prvSemaphoreTest, ( signed char * ) "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL );
00160         }
00161     }
00162 
00163     /* vQueueAddToRegistry() adds the semaphore to the registry, if one is
00164     in use.  The registry is provided as a means for kernel aware 
00165     debuggers to locate semaphores and has no purpose if a kernel aware debugger
00166     is not being used.  The call to vQueueAddToRegistry() will be removed
00167     by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is 
00168     defined to be less than 1. */
00169     vQueueAddToRegistry( ( xQueueHandle ) pxFirstSemaphoreParameters->xSemaphore, ( signed char * ) "Counting_Sem_1" );
00170     vQueueAddToRegistry( ( xQueueHandle ) pxSecondSemaphoreParameters->xSemaphore, ( signed char * ) "Counting_Sem_2" );
00171 }

portBASE_TYPE xAreSemaphoreTasksStillRunning ( void   ) 

Definition at line 266 of file semtest.c.

References pdFALSE, pdTRUE, portBASE_TYPE, sCheckVariables, and semtstNUM_TASKS.

Referenced by prvCheckOtherTasksAreStillRunning().

00267 {
00268 static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 };
00269 portBASE_TYPE xTask, xReturn = pdTRUE;
00270 
00271     for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ )
00272     {
00273         if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] )
00274         {
00275             xReturn = pdFALSE;
00276         }
00277 
00278         sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ];
00279     }
00280 
00281     return xReturn;
00282 }


Variable Documentation

volatile short sCheckVariables[semtstNUM_TASKS] = { 0 } [static]

Definition at line 110 of file semtest.c.

Referenced by portTASK_FUNCTION(), and xAreSemaphoreTasksStillRunning().

volatile short sNextCheckVariable = 0 [static]

Definition at line 111 of file semtest.c.

Referenced by portTASK_FUNCTION().


Generated on Thu Dec 17 20:02:01 2009 for AVR32 UC3 - FreeRTOS Real Time Kernel by  doxygen 1.5.5