In process of module testing event_groups.c.

Introduce xPortRunning variable into Win32 simulator port layer.
Add port optimised task selection macro for the GCC Win32 port layer (the MSVC version has had one for a while).
Ensure the event list item value does not get modified by code in tasks.c (priority inheritance, or priority change) when it is in use by the event group implementation.
This commit is contained in:
Richard Barry 2013-12-23 16:02:03 +00:00
parent 0147415c40
commit 64ad1c00b5
7 changed files with 322 additions and 134 deletions

View file

@ -148,6 +148,9 @@ static unsigned long (*ulIsrHandler[ portMAX_INTERRUPTS ])( void ) = { 0 };
/* Pointer to the TCB of the currently executing task. */
extern void *pxCurrentTCB;
/* Used to ensure nothing is processed during the startup sequence. */
static portBASE_TYPE xPortRunning = pdFALSE;
/*-----------------------------------------------------------*/
static DWORD WINAPI prvSimulatedPeripheralTimer( LPVOID lpParameter )
@ -190,6 +193,8 @@ TIMECAPS xTimeCaps;
Sleep( portTICK_RATE_MS );
}
configASSERT( xPortRunning );
WaitForSingleObject( pvInterruptEventMutex, INFINITE );
/* The timer has expired, generate the simulated tick event. */
@ -197,7 +202,10 @@ TIMECAPS xTimeCaps;
/* The interrupt is now pending - notify the simulated interrupt
handler thread. */
SetEvent( pvInterruptEvent );
if( ulCriticalNesting == 0 )
{
SetEvent( pvInterruptEvent );
}
/* Give back the mutex so the simulated interrupt handler unblocks
and can access the interrupt handler variables. */
@ -312,7 +320,7 @@ xThreadState *pxThreadState;
ulCriticalNesting = portNO_CRITICAL_NESTING;
/* Bump up the priority of the thread that is going to run, in the
hope that this will asist in getting the Windows thread scheduler to
hope that this will assist in getting the Windows thread scheduler to
behave as an embedded engineer might expect. */
ResumeThread( pxThreadState->pvThread );
@ -338,6 +346,7 @@ static unsigned long prvProcessTickInterrupt( void )
unsigned long ulSwitchRequired;
/* Process the tick itself. */
configASSERT( xPortRunning );
ulSwitchRequired = ( unsigned long ) xTaskIncrementTick();
return ulSwitchRequired;
@ -356,6 +365,13 @@ void *pvObjectList[ 2 ];
pvObjectList[ 0 ] = pvInterruptEventMutex;
pvObjectList[ 1 ] = pvInterruptEvent;
/* Create a pending tick to ensure the first task is started as soon as
this thread pends. */
ulPendingInterrupts |= ( 1 << portINTERRUPT_TICK );
SetEvent( pvInterruptEvent );
xPortRunning = pdTRUE;
for(;;)
{
WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE );
@ -489,6 +505,8 @@ void vPortEndScheduler( void )
void vPortGenerateSimulatedInterrupt( unsigned long ulInterruptNumber )
{
configASSERT( xPortRunning );
if( ( ulInterruptNumber < portMAX_INTERRUPTS ) && ( pvInterruptEventMutex != NULL ) )
{
/* Yield interrupts are processed even when critical nesting is non-zero. */
@ -528,7 +546,7 @@ void vPortSetInterruptHandler( unsigned long ulInterruptNumber, unsigned long (*
void vPortEnterCritical( void )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED )
if( xPortRunning == pdTRUE )
{
/* The interrupt event mutex is held for the entire critical section,
effectively disabling (simulated) interrupts. */
@ -561,6 +579,7 @@ long lMutexNeedsReleasing;
(simulated) disabled? */
if( ulPendingInterrupts != 0UL )
{
configASSERT( xPortRunning );
SetEvent( pvInterruptEvent );
/* Mutex will be released now, so does not require releasing
@ -577,9 +596,13 @@ long lMutexNeedsReleasing;
}
}
if( lMutexNeedsReleasing == pdTRUE )
if( pvInterruptEventMutex != NULL )
{
ReleaseMutex( pvInterruptEventMutex );
if( lMutexNeedsReleasing == pdTRUE )
{
configASSERT( xPortRunning );
ReleaseMutex( pvInterruptEventMutex );
}
}
}
/*-----------------------------------------------------------*/

View file

@ -99,8 +99,8 @@ void vPortCloseRunningThread( void *pvTaskToDelete, volatile portBASE_TYPE *pxPe
void vPortDeleteThread( void *pvThreadToDelete );
#define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB )
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) )
#define portDISABLE_INTERRUPTS()
#define portENABLE_INTERRUPTS()
#define portDISABLE_INTERRUPTS() vPortEnterCritical()
#define portENABLE_INTERRUPTS() vPortExitCritical()
/* Critical section handling. */
void vPortEnterCritical( void );
@ -109,27 +109,34 @@ void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#ifndef __GNUC__
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
#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 ) )
/* 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 ) )
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#ifdef __GNUC__
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
__asm volatile( "mov %0, %%eax \n\t" \
"bsr %%eax, %%eax \n\t" \
"mov %%eax, %1 \n\t" \
:"=r"(uxTopPriority) : "r"(uxReadyPriorities) : "eax" )
#else
/* BitScanReverse returns the bit position of the most significant '1'
in the word. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) )
#endif /* __GNUC__ */
#endif /* taskRECORD_READY_PRIORITY */
#endif /* taskRECORD_READY_PRIORITY */
#endif /* __GNUC__ */