Kernel optimisations.

pull/1/head
Richard Barry 12 years ago
parent c9d9bddc3c
commit ad8fa53043

@ -104,6 +104,38 @@
#ifndef LIST_H #ifndef LIST_H
#define LIST_H #define LIST_H
/*
* The list structure members are modified from within interrupts, and therefore
* by rights should be declared volatile. However, they are only modified in a
* functionally atomic way (within critical sections of with the scheduler
* suspended) and are either passed by reference into a function or indexed via
* a volatile variable. Therefore, in all use cases tested so far, the volatile
* qualifier can be omitted in order to provide a moderate performance
* improvement without adversely affecting functional behaviour. The assembly
* instructions generated by the IAR, ARM and GCC compilers when the respective
* compiler's options were set for maximum optimisation has been inspected and
* deemed to be as intended. That said, as compiler technology advances, and
* especially if aggressive cross module optimisation is used (a use case that
* has not been exercised to any great extend) then it is feasible that the
* volatile qualifier will be needed for correct optimisation. It is expected
* that a compiler removing essential code because, without the volatile
* qualifier on the list structure members and with aggressive cross module
* optimisation, the compiler deemed the code unnecessary will result in
* complete and obvious failure of the scheduler. If this is ever experienced
* then the volatile qualifier can be inserted in the relevant places within the
* list structures by simply defining configLIST_VOLATILE to volatile in
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
* If configLIST_VOLATILE is not defined then the preprocessor directives below
* will simply #define configLIST_VOLATILE away completely.
*
* To use volatile list structure members then add the following line to
* FreeRTOSConfig.h (without the quotes):
* "#define configLIST_VOLATILE volatile"
*/
#ifndef configLIST_VOLATILE
#define configLIST_VOLATILE
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -112,19 +144,19 @@ extern "C" {
*/ */
struct xLIST_ITEM struct xLIST_ITEM
{ {
portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ configLIST_VOLATILE portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next xListItem in the list. */
volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*< Pointer to the previous xListItem in the list. */
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
}; };
typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */
struct xMINI_LIST_ITEM struct xMINI_LIST_ITEM
{ {
portTickType xItemValue; configLIST_VOLATILE portTickType xItemValue;
volatile struct xLIST_ITEM *pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxNext;
volatile struct xLIST_ITEM *pxPrevious; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
}; };
typedef struct xMINI_LIST_ITEM xMiniListItem; typedef struct xMINI_LIST_ITEM xMiniListItem;
@ -133,9 +165,9 @@ typedef struct xMINI_LIST_ITEM xMiniListItem;
*/ */
typedef struct xLIST typedef struct xLIST
{ {
volatile unsigned portBASE_TYPE uxNumberOfItems; configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems;
volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
} xList; } xList;
/* /*
@ -286,7 +318,7 @@ xList * const pxConstList = ( pxList ); \
* \page vListInitialise vListInitialise * \page vListInitialise vListInitialise
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialise( xList *pxList ); void vListInitialise( xList * const pxList );
/* /*
* Must be called before a list item is used. This sets the list container to * Must be called before a list item is used. This sets the list container to
@ -297,7 +329,7 @@ void vListInitialise( xList *pxList );
* \page vListInitialiseItem vListInitialiseItem * \page vListInitialiseItem vListInitialiseItem
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialiseItem( xListItem *pxItem ); void vListInitialiseItem( xListItem * const pxItem );
/* /*
* Insert a list item into a list. The item will be inserted into the list in * Insert a list item into a list. The item will be inserted into the list in
@ -310,7 +342,7 @@ void vListInitialiseItem( xListItem *pxItem );
* \page vListInsert vListInsert * \page vListInsert vListInsert
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsert( xList *pxList, xListItem *pxNewListItem ); void vListInsert( xList * const pxList, xListItem * const pxNewListItem );
/* /*
* Insert a list item into a list. The item will be inserted in a position * Insert a list item into a list. The item will be inserted in a position
@ -331,7 +363,7 @@ void vListInsert( xList *pxList, xListItem *pxNewListItem );
* \page vListInsertEnd vListInsertEnd * \page vListInsertEnd vListInsertEnd
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ); void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem );
/* /*
* Remove an item from a list. The list item has a pointer to the list that * Remove an item from a list. The list item has a pointer to the list that
@ -346,7 +378,7 @@ void vListInsertEnd( xList *pxList, xListItem *pxNewListItem );
* \page uxListRemove uxListRemove * \page uxListRemove uxListRemove
* \ingroup LinkedList * \ingroup LinkedList
*/ */
unsigned portBASE_TYPE uxListRemove( xListItem *pxItemToRemove ); unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove );
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -81,7 +81,7 @@
* PUBLIC LIST API documented in list.h * PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/ *----------------------------------------------------------*/
void vListInitialise( xList *pxList ) void vListInitialise( xList * const pxList )
{ {
/* The list structure contains a list item which is used to mark the /* The list structure contains a list item which is used to mark the
end of the list. To initialise the list the list end is inserted end of the list. To initialise the list the list end is inserted
@ -101,16 +101,16 @@ void vListInitialise( xList *pxList )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInitialiseItem( xListItem *pxItem ) void vListInitialiseItem( xListItem * const pxItem )
{ {
/* Make sure the list item is not recorded as being on a list. */ /* Make sure the list item is not recorded as being on a list. */
pxItem->pvContainer = NULL; pxItem->pvContainer = NULL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ) void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem )
{ {
volatile xListItem * pxIndex; xListItem * pxIndex;
/* Insert a new list item into pxList, but rather than sort the list, /* Insert a new list item into pxList, but rather than sort the list,
makes the new list item the last item to be removed by a call to makes the new list item the last item to be removed by a call to
@ -119,8 +119,8 @@ volatile xListItem * pxIndex;
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
pxIndex->pxPrevious->pxNext = ( volatile xListItem * ) pxNewListItem; pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = ( volatile xListItem * ) pxNewListItem; pxIndex->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */ /* Remember which list the item is in. */
pxNewListItem->pvContainer = ( void * ) pxList; pxNewListItem->pvContainer = ( void * ) pxList;
@ -129,9 +129,9 @@ volatile xListItem * pxIndex;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsert( xList *pxList, xListItem *pxNewListItem ) void vListInsert( xList * const pxList, xListItem * const pxNewListItem )
{ {
volatile xListItem *pxIterator; xListItem *pxIterator;
portTickType xValueOfInsertion; portTickType xValueOfInsertion;
/* Insert the new list item into the list, sorted in ulListItem order. */ /* Insert the new list item into the list, sorted in ulListItem order. */
@ -175,9 +175,9 @@ portTickType xValueOfInsertion;
} }
pxNewListItem->pxNext = pxIterator->pxNext; pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator; pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem; pxIterator->pxNext = pxNewListItem;
/* Remember which list the item is in. This allows fast removal of the /* Remember which list the item is in. This allows fast removal of the
item later. */ item later. */
@ -187,7 +187,7 @@ portTickType xValueOfInsertion;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxListRemove( xListItem *pxItemToRemove ) unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove )
{ {
xList * pxList; xList * pxList;

@ -81,7 +81,7 @@
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -185,15 +185,21 @@
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#ifdef __cplusplus #ifdef __cplusplus
} } /* extern C */
#endif #endif
/* Suppress warnings that are generated by the IAR tools, but cannot be
fixed in the source code because to do so would cause other compilers to
generate warnings. */
#pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082
#endif /* __ICCARM__ */ #endif /* __ICCARM__ */

@ -245,9 +245,8 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
{ {
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -447,9 +446,8 @@ xQueueHandle xReturn = NULL;
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
{ {
portBASE_TYPE xReturn; portBASE_TYPE xReturn;
xQUEUE *pxMutex; xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
pxMutex = ( xQUEUE * ) xMutex;
configASSERT( pxMutex ); configASSERT( pxMutex );
/* If this is the task that holds the mutex then pxMutexHolder will not /* If this is the task that holds the mutex then pxMutexHolder will not
@ -498,9 +496,8 @@ xQueueHandle xReturn = NULL;
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
{ {
portBASE_TYPE xReturn; portBASE_TYPE xReturn;
xQUEUE *pxMutex; xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
pxMutex = ( xQUEUE * ) xMutex;
configASSERT( pxMutex ); configASSERT( pxMutex );
/* Comments regarding mutual exclusion as per those within /* Comments regarding mutual exclusion as per those within
@ -565,9 +562,8 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; xTimeOutType xTimeOut;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
@ -724,9 +720,8 @@ xQUEUE *pxQueue;
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; xTimeOutType xTimeOut;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
@ -804,9 +799,8 @@ xQUEUE *pxQueue;
signed portBASE_TYPE xEntryTimeSet = pdFALSE; signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; xTimeOutType xTimeOut;
signed char *pcOriginalReadPosition; signed char *pcOriginalReadPosition;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
@ -825,7 +819,7 @@ xQUEUE *pxQueue;
{ {
traceQUEUE_RECEIVE( pxQueue ); traceQUEUE_RECEIVE( pxQueue );
/* We are actually removing data. */ /* Data is actually being removed (not just peeked). */
--( pxQueue->uxMessagesWaiting ); --( pxQueue->uxMessagesWaiting );
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
@ -934,9 +928,8 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; unsigned portBASE_TYPE uxSavedInterruptStatus;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
@ -1048,9 +1041,8 @@ signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvB
signed portBASE_TYPE xEntryTimeSet = pdFALSE; signed portBASE_TYPE xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; xTimeOutType xTimeOut;
signed char *pcOriginalReadPosition; signed char *pcOriginalReadPosition;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
@ -1199,9 +1191,8 @@ signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvB
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; unsigned portBASE_TYPE uxSavedInterruptStatus;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
@ -1276,9 +1267,8 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuff
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; unsigned portBASE_TYPE uxSavedInterruptStatus;
signed char *pcOriginalReadPosition; signed char *pcOriginalReadPosition;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
@ -1353,9 +1343,8 @@ unsigned portBASE_TYPE uxReturn;
void vQueueDelete( xQueueHandle xQueue ) void vQueueDelete( xQueueHandle xQueue )
{ {
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
traceQUEUE_DELETE( pxQueue ); traceQUEUE_DELETE( pxQueue );
@ -1645,9 +1634,7 @@ signed portBASE_TYPE xReturn;
signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ) signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
/* If the queue is already full we may have to block. A critical section /* If the queue is already full we may have to block. A critical section
is required to prevent an interrupt removing something from the queue is required to prevent an interrupt removing something from the queue
@ -1716,9 +1703,7 @@ signed portBASE_TYPE xReturn;
signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ) signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
/* If the queue is already empty we may have to block. A critical section /* If the queue is already empty we may have to block. A critical section
is required to prevent an interrupt adding something to the queue is required to prevent an interrupt adding something to the queue
@ -1791,9 +1776,7 @@ signed portBASE_TYPE xReturn;
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
{ {
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
/* Cannot block within an ISR so if there is no space on the queue then /* Cannot block within an ISR so if there is no space on the queue then
exit without doing anything. */ exit without doing anything. */
@ -1826,9 +1809,7 @@ signed portBASE_TYPE xReturn;
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
{ {
signed portBASE_TYPE xReturn; signed portBASE_TYPE xReturn;
xQUEUE * pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
/* We cannot block from an ISR, so check there is data available. If /* We cannot block from an ISR, so check there is data available. If
not then just leave without doing anything. */ not then just leave without doing anything. */
@ -1917,9 +1898,7 @@ signed portBASE_TYPE xReturn;
void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
{ {
xQUEUE *pxQueue; xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
pxQueue = ( xQUEUE * ) xQueue;
/* This function should not be called by application code hence the /* This function should not be called by application code hence the
'Restricted' in its name. It is not part of the public API. It is 'Restricted' in its name. It is not part of the public API. It is
@ -1999,9 +1978,7 @@ signed portBASE_TYPE xReturn;
portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
{ {
portBASE_TYPE xReturn; portBASE_TYPE xReturn;
xQUEUE *pxQueueOrSemaphore; xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
{ {

@ -201,12 +201,11 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r
/* File private variables. --------------------------------*/ /* File private variables. --------------------------------*/
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U;
PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U;
PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = ( portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = ( portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY; PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
@ -214,7 +213,7 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTic
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
#endif #endif
@ -587,13 +586,6 @@ tskTCB * pxNewTCB;
} }
} }
/* Remember the top priority to make context switching faster. Use
the priority in pxNewTCB as this has been capped to a valid value. */
if( pxNewTCB->uxPriority > uxTopUsedPriority )
{
uxTopUsedPriority = pxNewTCB->uxPriority;
}
uxTaskNumber++; uxTaskNumber++;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
@ -662,7 +654,7 @@ tskTCB * pxNewTCB;
} }
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( pxTCB->xEventListItem.pvContainer != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
uxListRemove( &( pxTCB->xEventListItem ) ); uxListRemove( &( pxTCB->xEventListItem ) );
} }
@ -707,17 +699,21 @@ tskTCB * pxNewTCB;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Minor optimisation. The tick count cannot change in this
block. */
const portTickType xConstTickCount = xTickCount;
/* Generate the tick time at which the task wants to wake. */ /* Generate the tick time at which the task wants to wake. */
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
if( xTickCount < *pxPreviousWakeTime ) if( xConstTickCount < *pxPreviousWakeTime )
{ {
/* The tick count has overflowed since this function was /* The tick count has overflowed since this function was
lasted called. In this case the only time we should ever lasted called. In this case the only time we should ever
actually delay is if the wake time has also overflowed, actually delay is if the wake time has also overflowed,
and the wake time is greater than the tick time. When this and the wake time is greater than the tick time. When this
is the case it is as if neither time had overflowed. */ is the case it is as if neither time had overflowed. */
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
{ {
xShouldDelay = pdTRUE; xShouldDelay = pdTRUE;
} }
@ -727,7 +723,7 @@ tskTCB * pxNewTCB;
/* The tick time has not overflowed. In this case we will /* The tick time has not overflowed. In this case we will
delay if either the wake time has overflowed, and/or the delay if either the wake time has overflowed, and/or the
tick time is less than the wake time. */ tick time is less than the wake time. */
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
{ {
xShouldDelay = pdTRUE; xShouldDelay = pdTRUE;
} }
@ -825,9 +821,7 @@ tskTCB * pxNewTCB;
{ {
eTaskState eReturn; eTaskState eReturn;
xList *pxStateList; xList *pxStateList;
tskTCB *pxTCB; const tskTCB * const pxTCB = ( tskTCB * ) xTask;
pxTCB = ( tskTCB * ) xTask;
if( pxTCB == pxCurrentTCB ) if( pxTCB == pxCurrentTCB )
{ {
@ -1048,7 +1042,7 @@ tskTCB * pxNewTCB;
} }
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( pxTCB->xEventListItem.pvContainer != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
uxListRemove( &( pxTCB->xEventListItem ) ); uxListRemove( &( pxTCB->xEventListItem ) );
} }
@ -1126,15 +1120,11 @@ tskTCB * pxNewTCB;
void vTaskResume( xTaskHandle xTaskToResume ) void vTaskResume( xTaskHandle xTaskToResume )
{ {
tskTCB *pxTCB; tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
/* It does not make sense to resume the calling task. */ /* It does not make sense to resume the calling task. */
configASSERT( xTaskToResume ); configASSERT( xTaskToResume );
/* Remove the task from whichever list it is currently in, and place
it in the ready list. */
pxTCB = ( tskTCB * ) xTaskToResume;
/* The parameter cannot be NULL as it is impossible to resume the /* The parameter cannot be NULL as it is impossible to resume the
currently executing task. */ currently executing task. */
if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
@ -1172,7 +1162,7 @@ tskTCB * pxNewTCB;
portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
{ {
portBASE_TYPE xYieldRequired = pdFALSE; portBASE_TYPE xYieldRequired = pdFALSE;
tskTCB *pxTCB; tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
unsigned portBASE_TYPE uxSavedInterruptStatus; unsigned portBASE_TYPE uxSavedInterruptStatus;
configASSERT( xTaskToResume ); configASSERT( xTaskToResume );
@ -1195,8 +1185,6 @@ tskTCB * pxNewTCB;
http://www.freertos.org/RTOS-Cortex-M3-M4.html */ http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
pxTCB = ( tskTCB * ) xTaskToResume;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
@ -1522,11 +1510,17 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
#if ( configGENERATE_RUN_TIME_STATS == 1) #if ( configGENERATE_RUN_TIME_STATS == 1)
{ {
*pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); if( pulTotalRunTime != NULL )
{
*pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
}
} }
#else #else
{ {
*pulTotalRunTime = 0; if( pulTotalRunTime != NULL )
{
*pulTotalRunTime = 0;
}
} }
#endif #endif
} }
@ -1585,75 +1579,82 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
/* Increment the RTOS tick, switching the delayed and overflowed /* Increment the RTOS tick, switching the delayed and overflowed
delayed lists if it wraps to 0. */ delayed lists if it wraps to 0. */
++xTickCount; ++xTickCount;
if( xTickCount == ( portTickType ) 0U )
{
taskSWITCH_DELAYED_LISTS();
}
/* See if this tick has made a timeout expire. Tasks are stored in the
queue in the order of their wake time - meaning once one tasks has been
found whose block time has not expired there is no need not look any
further down the list. */
if( xTickCount >= xNextTaskUnblockTime )
{ {
for( ;; ) /* Minor optimisation. The tick count cannot change in this
block. */
const portTickType xConstTickCount = xTickCount;
if( xConstTickCount == ( portTickType ) 0U )
{ {
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) taskSWITCH_DELAYED_LISTS();
{ }
/* The delayed list is empty. Set xNextTaskUnblockTime to
the maximum possible value so it is extremely unlikely that /* See if this tick has made a timeout expire. Tasks are stored in the
the if( xTickCount >= xNextTaskUnblockTime ) test will pass queue in the order of their wake time - meaning once one tasks has been
next time through. */ found whose block time has not expired there is no need not look any
xNextTaskUnblockTime = portMAX_DELAY; further down the list. */
break; if( xConstTickCount >= xNextTaskUnblockTime )
} {
else for( ;; )
{ {
/* The delayed list is not empty, get the value of the item if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
at the head of the delayed list. This is the time at which
the task at the head of the delayed list must be removed
from the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xTickCount < xItemValue )
{ {
/* It is not time to unblock this item yet, but the item /* The delayed list is empty. Set xNextTaskUnblockTime to
value is the time at which the task at the head of the the maximum possible value so it is extremely unlikely that
blocked list must be removed from the Blocked state - the if( xTickCount >= xNextTaskUnblockTime ) test will pass
so record the item value in xNextTaskUnblockTime. */ next time through. */
xNextTaskUnblockTime = xItemValue; xNextTaskUnblockTime = portMAX_DELAY;
break; break;
} }
else
{
/* The delayed list is not empty, get the value of the item
at the head of the delayed list. This is the time at which
the task at the head of the delayed list must be removed
from the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xConstTickCount < xItemValue )
{
/* It is not time to unblock this item yet, but the item
value is the time at which the task at the head of the
blocked list must be removed from the Blocked state -
so record the item value in xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue;
break;
}
/* It is time to remove the item from the Blocked state. */ /* It is time to remove the item from the Blocked state. */
uxListRemove( &( pxTCB->xGenericListItem ) ); uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove it /* Is the task waiting on an event also? If so remove it
from the event list. */ from the event list. */
if( pxTCB->xEventListItem.pvContainer != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
uxListRemove( &( pxTCB->xEventListItem ) ); uxListRemove( &( pxTCB->xEventListItem ) );
} }
/* Place the unblocked task into the appropriate ready /* Place the unblocked task into the appropriate ready
list. */ list. */
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate context /* A task being unblocked cannot cause an immediate context
switch if preemption is turned off. */ switch if preemption is turned off. */
#if ( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
{
/* Preemption is on, but a context switch should only
be performed if the unblocked task has a priority that
is equal to or higher than the currently executing
task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
xSwitchRequired = pdTRUE; /* Preemption is on, but a context switch should only
be performed if the unblocked task has a priority that
is equal to or higher than the currently executing
task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
xSwitchRequired = pdTRUE;
}
} }
#endif /* configUSE_PREEMPTION */
} }
#endif /* configUSE_PREEMPTION */
} }
} }
} }
@ -1999,6 +2000,9 @@ portBASE_TYPE xReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Minor optimisation. The tick count cannot change in this block. */
const portTickType xConstTickCount = xTickCount;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
the maximum block time then the task should block indefinitely, and the maximum block time then the task should block indefinitely, and
@ -2010,7 +2014,7 @@ portBASE_TYPE xReturn;
else /* We are not blocking indefinitely, perform the checks below. */ else /* We are not blocking indefinitely, perform the checks below. */
#endif #endif
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xConstTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
{ {
/* The tick count is greater than the time at which vTaskSetTimeout() /* The tick count is greater than the time at which vTaskSetTimeout()
was called, but has also overflowed since vTaskSetTimeOut() was called. was called, but has also overflowed since vTaskSetTimeOut() was called.
@ -2018,10 +2022,10 @@ portBASE_TYPE xReturn;
passed since vTaskSetTimeout() was called. */ passed since vTaskSetTimeout() was called. */
xReturn = pdTRUE; xReturn = pdTRUE;
} }
else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait ) else if( ( ( portTickType ) ( ( portTickType ) xConstTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
{ {
/* Not a genuine timeout. Adjust parameters for time remaining. */ /* Not a genuine timeout. Adjust parameters for time remaining. */
*pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); *pxTicksToWait -= ( ( portTickType ) xConstTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
vTaskSetTimeOutState( pxTimeOut ); vTaskSetTimeOutState( pxTimeOut );
xReturn = pdFALSE; xReturn = pdFALSE;
} }
@ -2741,7 +2745,6 @@ tskTCB *pxNewTCB;
{ {
xTaskStatusType *pxTaskStatusArray; xTaskStatusType *pxTaskStatusArray;
volatile unsigned portBASE_TYPE uxArraySize, x; volatile unsigned portBASE_TYPE uxArraySize, x;
unsigned long ulTotalRunTime;
char cStatus; char cStatus;
/* /*
@ -2782,7 +2785,7 @@ tskTCB *pxNewTCB;
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
/* Generate the (binary) data. */ /* Generate the (binary) data. */
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime ); uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
/* Create a human readable table from the binary data. */ /* Create a human readable table from the binary data. */
for( x = 0; x < uxArraySize; x++ ) for( x = 0; x < uxArraySize; x++ )
@ -2825,7 +2828,7 @@ tskTCB *pxNewTCB;
{ {
xTaskStatusType *pxTaskStatusArray; xTaskStatusType *pxTaskStatusArray;
volatile unsigned portBASE_TYPE uxArraySize, x; volatile unsigned portBASE_TYPE uxArraySize, x;
unsigned long ulTotalRunTime, ulStatsAsPercentage; unsigned long ulTotalTime, ulStatsAsPercentage;
/* /*
* PLEASE NOTE: * PLEASE NOTE:
@ -2865,13 +2868,13 @@ tskTCB *pxNewTCB;
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
/* Generate the (binary) data. */ /* Generate the (binary) data. */
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime ); uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
/* For percentage calculations. */ /* For percentage calculations. */
ulTotalRunTime /= 100UL; ulTotalTime /= 100UL;
/* Avoid divide by zero errors. */ /* Avoid divide by zero errors. */
if( ulTotalRunTime > 0 ) if( ulTotalTime > 0 )
{ {
/* Create a human readable table from the binary data. */ /* Create a human readable table from the binary data. */
for( x = 0; x < uxArraySize; x++ ) for( x = 0; x < uxArraySize; x++ )
@ -2879,7 +2882,7 @@ tskTCB *pxNewTCB;
/* What percentage of the total run time has the task used? /* What percentage of the total run time has the task used?
This will always be rounded down to the nearest integer. This will always be rounded down to the nearest integer.
ulTotalRunTimeDiv100 has already been divided by 100. */ ulTotalRunTimeDiv100 has already been divided by 100. */
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime; ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
if( ulStatsAsPercentage > 0UL ) if( ulStatsAsPercentage > 0UL )
{ {

Loading…
Cancel
Save