mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Kernel optimisations.
This commit is contained in:
parent
c9d9bddc3c
commit
ad8fa53043
|
@ -104,6 +104,38 @@
|
|||
#ifndef 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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -112,19 +144,19 @@ extern "C" {
|
|||
*/
|
||||
struct xLIST_ITEM
|
||||
{
|
||||
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. */
|
||||
volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */
|
||||
configLIST_VOLATILE portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next 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 * 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. */
|
||||
|
||||
struct xMINI_LIST_ITEM
|
||||
{
|
||||
portTickType xItemValue;
|
||||
volatile struct xLIST_ITEM *pxNext;
|
||||
volatile struct xLIST_ITEM *pxPrevious;
|
||||
configLIST_VOLATILE portTickType xItemValue;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||
};
|
||||
typedef struct xMINI_LIST_ITEM xMiniListItem;
|
||||
|
||||
|
@ -133,9 +165,9 @@ typedef struct xMINI_LIST_ITEM xMiniListItem;
|
|||
*/
|
||||
typedef struct xLIST
|
||||
{
|
||||
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 (). */
|
||||
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. */
|
||||
configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems;
|
||||
xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -286,7 +318,7 @@ xList * const pxConstList = ( pxList ); \
|
|||
* \page vListInitialise vListInitialise
|
||||
* \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
|
||||
|
@ -297,7 +329,7 @@ void vListInitialise( xList *pxList );
|
|||
* \page vListInitialiseItem vListInitialiseItem
|
||||
* \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
|
||||
|
@ -310,7 +342,7 @@ void vListInitialiseItem( xListItem *pxItem );
|
|||
* \page vListInsert vListInsert
|
||||
* \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
|
||||
|
@ -331,7 +363,7 @@ void vListInsert( xList *pxList, xListItem *pxNewListItem );
|
|||
* \page vListInsertEnd vListInsertEnd
|
||||
* \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
|
||||
|
@ -346,7 +378,7 @@ void vListInsertEnd( xList *pxList, xListItem *pxNewListItem );
|
|||
* \page uxListRemove uxListRemove
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
unsigned portBASE_TYPE uxListRemove( xListItem *pxItemToRemove );
|
||||
unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
* 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
|
||||
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. */
|
||||
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,
|
||||
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->pxPrevious = pxIndex->pxPrevious;
|
||||
pxIndex->pxPrevious->pxNext = ( volatile xListItem * ) pxNewListItem;
|
||||
pxIndex->pxPrevious = ( volatile xListItem * ) pxNewListItem;
|
||||
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||
pxIndex->pxPrevious = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
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;
|
||||
|
||||
/* Insert the new list item into the list, sorted in ulListItem order. */
|
||||
|
@ -175,9 +175,9 @@ portTickType xValueOfInsertion;
|
|||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem;
|
||||
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem;
|
||||
pxIterator->pxNext = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
item later. */
|
||||
|
@ -187,7 +187,7 @@ portTickType xValueOfInsertion;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE uxListRemove( xListItem *pxItemToRemove )
|
||||
unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove )
|
||||
{
|
||||
xList * pxList;
|
||||
|
||||
|
|
|
@ -185,15 +185,21 @@
|
|||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
} /* extern C */
|
||||
#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__ */
|
||||
|
||||
|
||||
|
|
|
@ -245,9 +245,8 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
|
|||
|
||||
portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
|
||||
{
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
|
@ -447,9 +446,8 @@ xQueueHandle xReturn = NULL;
|
|||
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
xQUEUE *pxMutex;
|
||||
xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
|
||||
|
||||
pxMutex = ( xQUEUE * ) xMutex;
|
||||
configASSERT( pxMutex );
|
||||
|
||||
/* 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 xReturn;
|
||||
xQUEUE *pxMutex;
|
||||
xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
|
||||
|
||||
pxMutex = ( xQUEUE * ) xMutex;
|
||||
configASSERT( pxMutex );
|
||||
|
||||
/* 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;
|
||||
xTimeOutType xTimeOut;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
|
||||
|
@ -724,9 +720,8 @@ xQUEUE *pxQueue;
|
|||
{
|
||||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||
|
||||
|
@ -804,9 +799,8 @@ xQUEUE *pxQueue;
|
|||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
signed char *pcOriginalReadPosition;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||
|
||||
|
@ -825,7 +819,7 @@ xQUEUE *pxQueue;
|
|||
{
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
|
||||
/* We are actually removing data. */
|
||||
/* Data is actually being removed (not just peeked). */
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
@ -934,9 +928,8 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
|
|||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
|
||||
|
@ -1048,9 +1041,8 @@ signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvB
|
|||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
signed char *pcOriginalReadPosition;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
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;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
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;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
signed char *pcOriginalReadPosition;
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||
|
||||
|
@ -1353,9 +1343,8 @@ unsigned portBASE_TYPE uxReturn;
|
|||
|
||||
void vQueueDelete( xQueueHandle xQueue )
|
||||
{
|
||||
xQUEUE *pxQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
configASSERT( 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 xReturn;
|
||||
xQUEUE *pxQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
/* 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
|
||||
|
@ -1716,9 +1703,7 @@ signed portBASE_TYPE xReturn;
|
|||
signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
xQUEUE *pxQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
/* 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
|
||||
|
@ -1791,9 +1776,7 @@ signed portBASE_TYPE xReturn;
|
|||
|
||||
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
|
||||
{
|
||||
xQUEUE *pxQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
/* Cannot block within an ISR so if there is no space on the queue then
|
||||
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 xReturn;
|
||||
xQUEUE * pxQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
/* We cannot block from an ISR, so check there is data available. If
|
||||
not then just leave without doing anything. */
|
||||
|
@ -1917,9 +1898,7 @@ signed portBASE_TYPE xReturn;
|
|||
|
||||
void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
|
||||
{
|
||||
xQUEUE *pxQueue;
|
||||
|
||||
pxQueue = ( xQUEUE * ) xQueue;
|
||||
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
|
||||
|
||||
/* 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
|
||||
|
@ -1999,9 +1978,7 @@ signed portBASE_TYPE xReturn;
|
|||
portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
xQUEUE *pxQueueOrSemaphore;
|
||||
|
||||
pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
|
||||
xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
|
||||
|
||||
if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
|
||||
{
|
||||
|
|
|
@ -201,7 +201,6 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r
|
|||
/* File private variables. --------------------------------*/
|
||||
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 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 signed portBASE_TYPE xSchedulerRunning = pdFALSE;
|
||||
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
|
||||
|
@ -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++;
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
@ -662,7 +654,7 @@ tskTCB * pxNewTCB;
|
|||
}
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer != NULL )
|
||||
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
||||
{
|
||||
uxListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
@ -707,17 +699,21 @@ tskTCB * pxNewTCB;
|
|||
|
||||
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. */
|
||||
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
|
||||
|
||||
if( xTickCount < *pxPreviousWakeTime )
|
||||
if( xConstTickCount < *pxPreviousWakeTime )
|
||||
{
|
||||
/* The tick count has overflowed since this function was
|
||||
lasted called. In this case the only time we should ever
|
||||
actually delay is if the wake time has also overflowed,
|
||||
and the wake time is greater than the tick time. When this
|
||||
is the case it is as if neither time had overflowed. */
|
||||
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) )
|
||||
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
|
||||
{
|
||||
xShouldDelay = pdTRUE;
|
||||
}
|
||||
|
@ -727,7 +723,7 @@ tskTCB * pxNewTCB;
|
|||
/* The tick time has not overflowed. In this case we will
|
||||
delay if either the wake time has overflowed, and/or the
|
||||
tick time is less than the wake time. */
|
||||
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) )
|
||||
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
|
||||
{
|
||||
xShouldDelay = pdTRUE;
|
||||
}
|
||||
|
@ -825,9 +821,7 @@ tskTCB * pxNewTCB;
|
|||
{
|
||||
eTaskState eReturn;
|
||||
xList *pxStateList;
|
||||
tskTCB *pxTCB;
|
||||
|
||||
pxTCB = ( tskTCB * ) xTask;
|
||||
const tskTCB * const pxTCB = ( tskTCB * ) xTask;
|
||||
|
||||
if( pxTCB == pxCurrentTCB )
|
||||
{
|
||||
|
@ -1048,7 +1042,7 @@ tskTCB * pxNewTCB;
|
|||
}
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer != NULL )
|
||||
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
||||
{
|
||||
uxListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
@ -1126,15 +1120,11 @@ tskTCB * pxNewTCB;
|
|||
|
||||
void vTaskResume( xTaskHandle xTaskToResume )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
|
||||
|
||||
/* It does not make sense to resume the calling task. */
|
||||
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
|
||||
currently executing task. */
|
||||
if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
|
||||
|
@ -1172,7 +1162,7 @@ tskTCB * pxNewTCB;
|
|||
portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
|
||||
{
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
tskTCB *pxTCB;
|
||||
tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
|
||||
configASSERT( xTaskToResume );
|
||||
|
@ -1195,8 +1185,6 @@ tskTCB * pxNewTCB;
|
|||
http://www.freertos.org/RTOS-Cortex-M3-M4.html */
|
||||
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||
|
||||
pxTCB = ( tskTCB * ) xTaskToResume;
|
||||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||
|
@ -1521,13 +1509,19 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
|||
#endif
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1)
|
||||
{
|
||||
if( pulTotalRunTime != NULL )
|
||||
{
|
||||
*pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
if( pulTotalRunTime != NULL )
|
||||
{
|
||||
*pulTotalRunTime = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1585,7 +1579,13 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
|
|||
/* Increment the RTOS tick, switching the delayed and overflowed
|
||||
delayed lists if it wraps to 0. */
|
||||
++xTickCount;
|
||||
if( xTickCount == ( portTickType ) 0U )
|
||||
|
||||
{
|
||||
/* Minor optimisation. The tick count cannot change in this
|
||||
block. */
|
||||
const portTickType xConstTickCount = xTickCount;
|
||||
|
||||
if( xConstTickCount == ( portTickType ) 0U )
|
||||
{
|
||||
taskSWITCH_DELAYED_LISTS();
|
||||
}
|
||||
|
@ -1594,7 +1594,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
|
|||
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 )
|
||||
if( xConstTickCount >= xNextTaskUnblockTime )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
|
@ -1616,7 +1616,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
|
|||
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
|
||||
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
if( xTickCount < xItemValue )
|
||||
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
|
||||
|
@ -1631,7 +1631,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
|
|||
|
||||
/* Is the task waiting on an event also? If so remove it
|
||||
from the event list. */
|
||||
if( pxTCB->xEventListItem.pvContainer != NULL )
|
||||
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
||||
{
|
||||
uxListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
@ -1657,6 +1657,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tasks of equal priority to the currently running task will share
|
||||
processing time (time slice) if preemption is on, and the application
|
||||
|
@ -1999,6 +2000,9 @@ portBASE_TYPE xReturn;
|
|||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Minor optimisation. The tick count cannot change in this block. */
|
||||
const portTickType xConstTickCount = xTickCount;
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
|
||||
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. */
|
||||
#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()
|
||||
was called, but has also overflowed since vTaskSetTimeOut() was called.
|
||||
|
@ -2018,10 +2022,10 @@ portBASE_TYPE xReturn;
|
|||
passed since vTaskSetTimeout() was called. */
|
||||
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. */
|
||||
*pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
|
||||
*pxTicksToWait -= ( ( portTickType ) xConstTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
|
||||
vTaskSetTimeOutState( pxTimeOut );
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
@ -2741,7 +2745,6 @@ tskTCB *pxNewTCB;
|
|||
{
|
||||
xTaskStatusType *pxTaskStatusArray;
|
||||
volatile unsigned portBASE_TYPE uxArraySize, x;
|
||||
unsigned long ulTotalRunTime;
|
||||
char cStatus;
|
||||
|
||||
/*
|
||||
|
@ -2782,7 +2785,7 @@ tskTCB *pxNewTCB;
|
|||
if( pxTaskStatusArray != NULL )
|
||||
{
|
||||
/* Generate the (binary) data. */
|
||||
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
|
||||
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
|
||||
|
||||
/* Create a human readable table from the binary data. */
|
||||
for( x = 0; x < uxArraySize; x++ )
|
||||
|
@ -2825,7 +2828,7 @@ tskTCB *pxNewTCB;
|
|||
{
|
||||
xTaskStatusType *pxTaskStatusArray;
|
||||
volatile unsigned portBASE_TYPE uxArraySize, x;
|
||||
unsigned long ulTotalRunTime, ulStatsAsPercentage;
|
||||
unsigned long ulTotalTime, ulStatsAsPercentage;
|
||||
|
||||
/*
|
||||
* PLEASE NOTE:
|
||||
|
@ -2865,13 +2868,13 @@ tskTCB *pxNewTCB;
|
|||
if( pxTaskStatusArray != NULL )
|
||||
{
|
||||
/* Generate the (binary) data. */
|
||||
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
|
||||
uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
|
||||
|
||||
/* For percentage calculations. */
|
||||
ulTotalRunTime /= 100UL;
|
||||
ulTotalTime /= 100UL;
|
||||
|
||||
/* Avoid divide by zero errors. */
|
||||
if( ulTotalRunTime > 0 )
|
||||
if( ulTotalTime > 0 )
|
||||
{
|
||||
/* Create a human readable table from the binary data. */
|
||||
for( x = 0; x < uxArraySize; x++ )
|
||||
|
@ -2879,7 +2882,7 @@ tskTCB *pxNewTCB;
|
|||
/* What percentage of the total run time has the task used?
|
||||
This will always be rounded down to the nearest integer.
|
||||
ulTotalRunTimeDiv100 has already been divided by 100. */
|
||||
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
|
||||
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
|
||||
|
||||
if( ulStatsAsPercentage > 0UL )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue