Introduced configUSE_PORT_OPTIMISED_TASK_SELECTION, and updated the MSVC simulator port as the first implementation.

This commit is contained in:
Richard Barry 2012-09-23 14:35:12 +00:00
parent 8ef7f03536
commit 670d172cfc
4 changed files with 112 additions and 17 deletions

View File

@ -104,7 +104,7 @@
#define configTIMER_QUEUE_LENGTH 20 #define configTIMER_QUEUE_LENGTH 20
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 7 ) #define configMAX_PRIORITIES ( 7 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
@ -132,4 +132,9 @@ to exclude the API function. */
extern void vAssertCalled( void ); extern void vAssertCalled( void );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled() #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled()
/* configUSE_PORT_OPTIMISED_TASK_SELECTION is only available in the MSVC
version of the Win32 simulator projects. It will be ignored in the GCC
version. */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif /* FREERTOS_CONFIG_H */ #endif /* FREERTOS_CONFIG_H */

View File

@ -165,6 +165,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define INCLUDE_uxTaskGetStackHighWaterMark 0 #define INCLUDE_uxTaskGetStackHighWaterMark 0
#endif #endif
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#endif
#ifndef INCLUDE_cTaskStateGet #ifndef INCLUDE_cTaskStateGet
#define INCLUDE_cTaskStateGet 0 #define INCLUDE_cTaskStateGet 0
#endif #endif

View File

@ -108,6 +108,30 @@ void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#ifndef __GNUC__
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */
#if( configMAX_PRIORITIES >= 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
/* BitScanReverse returns the bit position of the most significant '1'
in the word. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) )
#endif /* taskRECORD_READY_PRIORITY */
#endif /* __GNUC__ */
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )

View File

@ -210,6 +210,72 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 0
/*
* uxTopReadyPriority holds the priority of the highest priority ready
* state task.
*/
#define taskRECORD_READY_PRIORITY( uxPriority ) \
{ \
if( ( uxPriority ) > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = ( uxPriority ); \
} \
} /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
/* Find the highest priority queue that contains ready tasks. */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
{ \
configASSERT( uxTopReadyPriority ); \
--uxTopReadyPriority; \
} \
\
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
the same priority get an equal share of the processor time. */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */
/*-----------------------------------------------------------*/
/* Define away taskCHECK_READY_LIST() as it is not required in this
configuration. */
#define taskCHECK_READY_LIST( uxPriority )
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* A port optimised version is provided. Call the port defined macros. */
#define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
/*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
unsigned portBASE_TYPE uxTopPriority; \
\
/* Find the highest priority queue that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
/*-----------------------------------------------------------*/
/* Let the port layer know if the ready list is empty so
taskSELECT_HIGHEST_PRIORITY_TASK() can function correctly. */
#define taskCHECK_READY_LIST( uxPriority ) \
{ \
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
{ \
portRESET_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority ); \
} \
} /* taskCHECK_READY_LIST() */
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* /*
* Place the task represented by pxTCB into the appropriate ready queue for * Place the task represented by pxTCB into the appropriate ready queue for
* the task. It is inserted at the end of the list. One quirk of this is * the task. It is inserted at the end of the list. One quirk of this is
@ -219,10 +285,7 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
*/ */
#define prvAddTaskToReadyQueue( pxTCB ) \ #define prvAddTaskToReadyQueue( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
if( ( pxTCB )->uxPriority > uxTopReadyPriority ) \ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
{ \
uxTopReadyPriority = ( pxTCB )->uxPriority; \
} \
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -579,6 +642,7 @@ tskTCB * pxNewTCB;
the termination list and free up any memory allocated by the the termination list and free up any memory allocated by the
scheduler for the TCB and stack. */ scheduler for the TCB and stack. */
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxTCB->uxPriority );
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( pxTCB->xEventListItem.pvContainer != NULL ) if( pxTCB->xEventListItem.pvContainer != NULL )
@ -671,6 +735,7 @@ tskTCB * pxNewTCB;
ourselves to the blocked list as the same list item is used for ourselves to the blocked list as the same list item is used for
both lists. */ both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxCurrentTCB->uxPriority );
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
} }
@ -717,6 +782,7 @@ tskTCB * pxNewTCB;
ourselves to the blocked list as the same list item is used for ourselves to the blocked list as the same list item is used for
both lists. */ both lists. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxCurrentTCB->uxPriority );
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
@ -910,6 +976,7 @@ tskTCB * pxNewTCB;
it to it's new ready list. As we are in a critical section we it to it's new ready list. As we are in a critical section we
can do this even if the scheduler is suspended. */ can do this even if the scheduler is suspended. */
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
taskCHECK_READY_LIST( uxCurrentPriority );
prvAddTaskToReadyQueue( pxTCB ); prvAddTaskToReadyQueue( pxTCB );
} }
@ -947,6 +1014,7 @@ tskTCB * pxNewTCB;
/* Remove task from the ready/delayed list and place in the suspended list. */ /* Remove task from the ready/delayed list and place in the suspended list. */
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxTCB->uxPriority );
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( pxTCB->xEventListItem.pvContainer != NULL ) if( pxTCB->xEventListItem.pvContainer != NULL )
@ -1690,16 +1758,7 @@ void vTaskSwitchContext( void )
taskFIRST_CHECK_FOR_STACK_OVERFLOW(); taskFIRST_CHECK_FOR_STACK_OVERFLOW();
taskSECOND_CHECK_FOR_STACK_OVERFLOW(); taskSECOND_CHECK_FOR_STACK_OVERFLOW();
/* Find the highest priority queue that contains ready tasks. */ taskSELECT_HIGHEST_PRIORITY_TASK();
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
{
configASSERT( uxTopReadyPriority );
--uxTopReadyPriority;
}
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the
same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
traceTASK_SWITCHED_IN(); traceTASK_SWITCHED_IN();
} }
@ -1724,7 +1783,7 @@ portTickType xTimeToWake;
to the blocked list as the same list item is used for both lists. We have to the blocked list as the same list item is used for both lists. We have
exclusive access to the ready lists as the scheduler is locked. */ exclusive access to the ready lists as the scheduler is locked. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxCurrentTCB->uxPriority );
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
{ {
@ -1778,6 +1837,7 @@ portTickType xTimeToWake;
blocked list as the same list item is used for both lists. This blocked list as the same list item is used for both lists. This
function is called form a critical section. */ function is called form a critical section. */
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxCurrentTCB->uxPriority );
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */ not occur. This may overflow but this doesn't matter. */
@ -2458,6 +2518,7 @@ tskTCB *pxNewTCB;
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
{ {
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxTCB->uxPriority );
/* Inherit the priority before being moved into the new list. */ /* Inherit the priority before being moved into the new list. */
pxTCB->uxPriority = pxCurrentTCB->uxPriority; pxTCB->uxPriority = pxCurrentTCB->uxPriority;
@ -2490,6 +2551,7 @@ tskTCB *pxNewTCB;
/* We must be the running task to be able to give the mutex back. /* We must be the running task to be able to give the mutex back.
Remove ourselves from the ready list we currently appear in. */ Remove ourselves from the ready list we currently appear in. */
vListRemove( &( pxTCB->xGenericListItem ) ); vListRemove( &( pxTCB->xGenericListItem ) );
taskCHECK_READY_LIST( pxTCB->uxPriority );
/* Disinherit the priority before adding the task into the new /* Disinherit the priority before adding the task into the new
ready list. */ ready list. */