#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 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 ) |
#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 |
typedef struct SEMAPHORE_PARAMETERS xSemaphoreParameters |
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 }
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] |