Some time and code size optimisations.
diff --git a/Source/croutine.c b/Source/croutine.c
index f180a87..61ada1c 100644
--- a/Source/croutine.c
+++ b/Source/croutine.c
@@ -222,7 +222,7 @@
/* Are there any co-routines waiting to get moved to the ready list? These
are co-routines that have been readied by an ISR. The ISR cannot access
the ready lists itself. */
- while( !listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) )
+ while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{
corCRCB *pxUnblockedCRCB;
@@ -263,8 +263,10 @@
}
/* See if this tick has made a timeout expire. */
- while( ( pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ) ) != NULL )
- {
+ while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
+ {
+ pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
+
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
{
/* Timeout not yet expired. */
@@ -352,7 +354,8 @@
signed portBASE_TYPE xReturn;
/* This function is called from within an interrupt. It can only access
- event lists and the pending ready list. */
+ event lists and the pending ready list. This function assumes that a
+ check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
diff --git a/Source/include/list.h b/Source/include/list.h
index 5a09fd1..ec1d08c 100644
--- a/Source/include/list.h
+++ b/Source/include/list.h
@@ -214,7 +214,7 @@
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
* \ingroup LinkedList
*/
-#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( pxList->uxNumberOfItems != ( unsigned portBASE_TYPE ) 0 ) ? ( (&( pxList->xListEnd ))->pxNext->pvOwner ) : ( NULL ) )
+#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( pxList->xListEnd ))->pxNext->pvOwner )
/*
* Check to see if a list item is within a list. The list item maintains a
diff --git a/Source/queue.c b/Source/queue.c
index a62d179..30c30b0 100644
--- a/Source/queue.c
+++ b/Source/queue.c
@@ -697,7 +697,7 @@
/* The data is being left in the queue, so see if there are
any other tasks waiting for the data. */
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
/* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */
@@ -790,7 +790,7 @@
be done when the queue is unlocked later. */
if( pxQueue->xTxLock == queueUNLOCKED )
{
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
@@ -880,7 +880,7 @@
/* The data is being left in the queue, so see if there are
any other tasks waiting for the data. */
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
/* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */
@@ -988,7 +988,7 @@
that an ISR has removed data while the queue was locked. */
if( pxQueue->xRxLock == queueUNLOCKED )
{
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
@@ -1117,7 +1117,7 @@
{
/* Data was posted while the queue was locked. Are any tasks
blocked waiting for data to become available? */
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
/* Tasks that are removed from the event list will get added to
the pending ready list as the scheduler is still suspended. */
@@ -1145,7 +1145,7 @@
{
while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
{
- if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
diff --git a/Source/tasks.c b/Source/tasks.c
index 120f8f7..965d0a0 100644
--- a/Source/tasks.c
+++ b/Source/tasks.c
@@ -161,6 +161,7 @@
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
+PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
#if ( configGENERATE_RUN_TIME_STATS == 1 )
@@ -220,10 +221,10 @@
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
{ \
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
- *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
- pcTraceBuffer += sizeof( unsigned long ); \
- *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
- pcTraceBuffer += sizeof( unsigned long ); \
+ *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
+ pcTraceBuffer += sizeof( unsigned long ); \
+ *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
+ pcTraceBuffer += sizeof( unsigned long ); \
} \
else \
{ \
@@ -265,24 +266,57 @@
* once one tasks has been found whose timer has not expired we need not look
* any further down the list.
*/
-#define prvCheckDelayedTasks() \
-{ \
-register tskTCB *pxTCB; \
- \
- while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
- { \
- if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
- { \
- break; \
- } \
- vListRemove( &( pxTCB->xGenericListItem ) ); \
- /* Is the task waiting on an event also? */ \
- if( pxTCB->xEventListItem.pvContainer ) \
- { \
- vListRemove( &( pxTCB->xEventListItem ) ); \
- } \
- prvAddTaskToReadyQueue( pxTCB ); \
- } \
+#define prvCheckDelayedTasks() \
+{ \
+register tskTCB *pxTCB; \
+portTickType xItemValue; \
+ \
+ /* Is the tick count greater than or equal to the wake time of the first \
+ task referenced from the delayed tasks list? */ \
+ if( xTickCount >= xNextTaskUnblockTime ) \
+ { \
+ for( ;; ) \
+ { \
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
+ { \
+ /* The delayed list is empty. Set xNextTaskUnblockTime to the \
+ maximum possible value so it is extremely unlikely that the \
+ if( xTickCount >= xNextTaskUnblockTime ) test will pass next \
+ time through. */ \
+ xNextTaskUnblockTime = portMAX_DELAY; \
+ 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 should 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 \
+ value is the time at which the task at the head of the \
+ blocked list should 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. */ \
+ vListRemove( &( pxTCB->xGenericListItem ) ); \
+ \
+ /* Is the task waiting on an event also? */ \
+ if( pxTCB->xEventListItem.pvContainer ) \
+ { \
+ vListRemove( &( pxTCB->xEventListItem ) ); \
+ } \
+ prvAddTaskToReadyQueue( pxTCB ); \
+ } \
+ } \
+ } \
}
/*-----------------------------------------------------------*/
@@ -343,6 +377,12 @@
static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
/*
+ * The currently executing task is entering the Blocked state. Add the task to
+ * either the current or the overflow delayed task list.
+ */
+static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
+
+/*
* Allocates memory from the heap for a TCB and associated stack. Checks the
* allocation was successful.
*/
@@ -637,7 +677,7 @@
/* Update the wake time ready for the next call. */
*pxPreviousWakeTime = xTimeToWake;
- if( xShouldDelay )
+ if( xShouldDelay != pdFALSE )
{
traceTASK_DELAY_UNTIL();
@@ -645,22 +685,7 @@
ourselves to the blocked list as the same list item is used for
both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
-
- /* The list item will be inserted in wake time order. */
- listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
-
- if( xTimeToWake < xTickCount )
- {
- /* Wake time has overflowed. Place this item in the
- overflow list. */
- vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* The wake time has not overflowed, so we can use the
- current block list. */
- vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
xAlreadyYielded = xTaskResumeAll();
@@ -706,22 +731,7 @@
ourselves to the blocked list as the same list item is used for
both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
-
- /* The list item will be inserted in wake time order. */
- listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
-
- if( xTimeToWake < xTickCount )
- {
- /* Wake time has overflowed. Place this item in the
- overflow list. */
- vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* The wake time has not overflowed, so we can use the
- current block list. */
- vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
}
xAlreadyYielded = xTaskResumeAll();
}
@@ -1125,8 +1135,9 @@
/* Move any readied tasks from the pending list into the
appropriate ready list. */
- while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
+ while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE )
{
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) );
vListRemove( &( pxTCB->xEventListItem ) );
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
@@ -1413,6 +1424,25 @@
pxDelayedTaskList = pxOverflowDelayedTaskList;
pxOverflowDelayedTaskList = pxTemp;
xNumOfOverflows++;
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ {
+ /* The delayed list is empty. Set xNextTaskUnblockTime to the
+ maximum possible value so it is extremely unlikely that the
+ if( xTickCount >= xNextTaskUnblockTime ) test will pass
+ until there is an item in the delayed list. */
+ xNextTaskUnblockTime = portMAX_DELAY;
+ }
+ else
+ {
+ tskTCB * pxTCB;
+
+ /* 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 should be removed from
+ the Blocked state. */
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
+ xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
+ }
}
/* See if this tick has made a timeout expire. */
@@ -1672,19 +1702,7 @@
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */
xTimeToWake = xTickCount + xTicksToWait;
-
- listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
-
- if( xTimeToWake < xTickCount )
- {
- /* Wake time has overflowed. Place this item in the overflow list. */
- vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* The wake time has not overflowed, so we can use the current block list. */
- vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else
@@ -1692,19 +1710,7 @@
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */
xTimeToWake = xTickCount + xTicksToWait;
-
- listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
-
- if( xTimeToWake < xTickCount )
- {
- /* Wake time has overflowed. Place this item in the overflow list. */
- vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* The wake time has not overflowed, so we can use the current block list. */
- vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
- }
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif
}
@@ -1724,7 +1730,10 @@
If an event is for a queue that is locked then this function will never
get called - the lock count on the queue will get modified instead. This
- means we can always expect exclusive access to the event list here. */
+ means we can always expect exclusive access to the event list here.
+
+ This function assumes that a check has already been made to ensure that
+ pxEventList is not empty. */
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
vListRemove( &( pxUnblockedTCB->xEventListItem ) );
@@ -2020,7 +2029,7 @@
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
xTaskResumeAll();
- if( !xListIsEmpty )
+ if( xListIsEmpty == pdFALSE )
{
tskTCB *pxTCB;
@@ -2041,6 +2050,32 @@
}
/*-----------------------------------------------------------*/
+static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
+{
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+ if( xTimeToWake < xTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow list. */
+ vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so we can use the current block list. */
+ vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
+
+ /* If the task entering the blocked state was placed at the head of the
+ list of blocked tasks then xNextTaskUnmblockTime needs to be updated
+ too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
{
tskTCB *pxNewTCB;