mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Add trace macros into the event groups implementation.
Add a task pre-delete hook to allow the insertion of any port specific clean up when a task is deleted. Increase use of 'const' qualifiers. Add vPortCloseRunningThread() into the Win32 port layer to attempt to allow Windows threads to be closed more gracefully when a task deletes itself.
This commit is contained in:
parent
0416289066
commit
6b3393b4b6
|
@ -128,6 +128,11 @@ xEVENT_BITS *pxEventBits;
|
||||||
{
|
{
|
||||||
pxEventBits->uxEventBits = 0;
|
pxEventBits->uxEventBits = 0;
|
||||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||||
|
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_CREATE_FAILED();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ( xEventGroupHandle ) pxEventBits;
|
return ( xEventGroupHandle ) pxEventBits;
|
||||||
|
@ -148,6 +153,8 @@ portBASE_TYPE xYieldedAlready;
|
||||||
|
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
|
traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
uxOriginalBitValue = pxEventBits->uxEventBits;
|
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||||
|
@ -172,6 +179,11 @@ portBASE_TYPE xYieldedAlready;
|
||||||
task's event list item so the kernel knows when a match is
|
task's event list item so the kernel knows when a match is
|
||||||
found. Then enter the blocked state. */
|
found. Then enter the blocked state. */
|
||||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | taskCLEAR_EVENTS_ON_EXIT_BIT | taskWAIT_FOR_ALL_BITS ), xTicksToWait );
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | taskCLEAR_EVENTS_ON_EXIT_BIT | taskWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||||
|
|
||||||
|
/* This is obsolete as it will get set after the task unblocks,
|
||||||
|
but some compilers mistakenly generate a warning about the
|
||||||
|
variable being returned without being set if it is not done. */
|
||||||
|
uxReturn = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -209,6 +221,7 @@ portBASE_TYPE xYieldedAlready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn );
|
||||||
return uxReturn;
|
return uxReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -232,6 +245,8 @@ xEventBitsType uxReturn, uxControlBits = 0;
|
||||||
{
|
{
|
||||||
const xEventBitsType uxCurrentEventBits = pxEventBits->uxEventBits;
|
const xEventBitsType uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor );
|
||||||
|
|
||||||
if( xWaitForAllBits == pdFALSE )
|
if( xWaitForAllBits == pdFALSE )
|
||||||
{
|
{
|
||||||
/* Task only has to wait for one bit within uxBitsToWaitFor to be set. Is
|
/* Task only has to wait for one bit within uxBitsToWaitFor to be set. Is
|
||||||
|
@ -288,6 +303,11 @@ xEventBitsType uxReturn, uxControlBits = 0;
|
||||||
found. Then enter the blocked state. */
|
found. Then enter the blocked state. */
|
||||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||||
portYIELD_WITHIN_API();
|
portYIELD_WITHIN_API();
|
||||||
|
|
||||||
|
/* This is obsolete as it will get set after the task unblocks, but
|
||||||
|
some compilers mistakenly generate a warning about the variable
|
||||||
|
being returned without being set if it is not done. */
|
||||||
|
uxReturn = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
@ -313,6 +333,7 @@ xEventBitsType uxReturn, uxControlBits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn );
|
||||||
return uxReturn;
|
return uxReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -329,6 +350,8 @@ xEventBitsType uxReturn;
|
||||||
uxBitsToClear = ~uxBitsToClear;
|
uxBitsToClear = ~uxBitsToClear;
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
|
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, ~uxBitsToClear );
|
||||||
|
|
||||||
/* The value returned is the event group value prior to the bits being
|
/* The value returned is the event group value prior to the bits being
|
||||||
cleared. */
|
cleared. */
|
||||||
uxReturn = pxEventBits->uxEventBits;
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
@ -359,6 +382,8 @@ portBASE_TYPE xMatchFound = pdFALSE;
|
||||||
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
|
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
pxListItem = listGET_HEAD_ENTRY( pxList );
|
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||||
|
|
||||||
/* Set the bits. */
|
/* Set the bits. */
|
||||||
|
@ -432,6 +457,8 @@ const xList *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||||
|
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
|
traceEVENT_GROUP_DELETE( xEventGroup );
|
||||||
|
|
||||||
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( unsigned portBASE_TYPE ) 0 )
|
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( unsigned portBASE_TYPE ) 0 )
|
||||||
{
|
{
|
||||||
/* Unblock the task, returning 0 as the event list is being deleted
|
/* Unblock the task, returning 0 as the event list is being deleted
|
||||||
|
|
|
@ -156,13 +156,13 @@ typedef portTickType xEventBitsType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if configUSE_CO_ROUTINES != 0
|
#if configUSE_CO_ROUTINES != 0
|
||||||
#if configMAX_CO_ROUTINE_PRIORITIES < 1
|
#ifndef configMAX_CO_ROUTINE_PRIORITIES
|
||||||
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
|
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if configMAX_PRIORITIES < 1
|
#ifndef configMAX_PRIORITIES
|
||||||
#error configMAX_PRIORITIES must be greater than or equal to 1.
|
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef INCLUDE_xTaskGetIdleTaskHandle
|
#ifndef INCLUDE_xTaskGetIdleTaskHandle
|
||||||
|
@ -294,6 +294,10 @@ typedef portTickType xEventBitsType;
|
||||||
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
|
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef portPRE_DELETE_HOOK
|
||||||
|
#define portPRE_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef portSETUP_TCB
|
#ifndef portSETUP_TCB
|
||||||
#define portSETUP_TCB( pxTCB ) ( void ) pxTCB
|
#define portSETUP_TCB( pxTCB ) ( void ) pxTCB
|
||||||
#endif
|
#endif
|
||||||
|
@ -551,6 +555,42 @@ typedef portTickType xEventBitsType;
|
||||||
#define traceFREE( pvAddress, uiSize )
|
#define traceFREE( pvAddress, uiSize )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_CREATE
|
||||||
|
#define traceEVENT_GROUP_CREATE( xEventGroup )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_CREATE_FAILED
|
||||||
|
#define traceEVENT_GROUP_CREATE_FAILED()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_SYNC_START
|
||||||
|
#define traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_SYNC_END
|
||||||
|
#define traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_WAIT_BITS_START
|
||||||
|
#define traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_WAIT_BITS_END
|
||||||
|
#define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_CLEAR_BITS
|
||||||
|
#define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_SET_BITS
|
||||||
|
#define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceEVENT_GROUP_DELETE
|
||||||
|
#define traceEVENT_GROUP_DELETE( xEventGroup )
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef configGENERATE_RUN_TIME_STATS
|
#ifndef configGENERATE_RUN_TIME_STATS
|
||||||
#define configGENERATE_RUN_TIME_STATS 0
|
#define configGENERATE_RUN_TIME_STATS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1412,8 +1412,8 @@ portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
|
||||||
* portTICK_RATE_MS can be used to convert kernel ticks into a real time
|
* portTICK_RATE_MS can be used to convert kernel ticks into a real time
|
||||||
* period.
|
* period.
|
||||||
*/
|
*/
|
||||||
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
void vTaskPlaceOnEventList( xList * const pxEventList, const portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, const portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
|
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
|
||||||
|
|
|
@ -244,6 +244,7 @@ char *pcTopOfStack = ( char * ) pxTopOfStack;
|
||||||
|
|
||||||
/* Create the thread itself. */
|
/* Create the thread itself. */
|
||||||
pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );
|
pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );
|
||||||
|
configASSERT( pxThreadState->pvThread );
|
||||||
SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );
|
SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );
|
||||||
SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );
|
SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );
|
||||||
SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_IDLE );
|
SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_IDLE );
|
||||||
|
@ -418,14 +419,52 @@ void vPortDeleteThread( void *pvTaskToDelete )
|
||||||
{
|
{
|
||||||
xThreadState *pxThreadState;
|
xThreadState *pxThreadState;
|
||||||
|
|
||||||
WaitForSingleObject( pvInterruptEventMutex, INFINITE );
|
|
||||||
|
|
||||||
/* Find the handle of the thread being deleted. */
|
/* Find the handle of the thread being deleted. */
|
||||||
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );
|
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );
|
||||||
|
|
||||||
|
/* Check that the thread is still valid, it might have been closed by
|
||||||
|
vPortCloseRunningThread() - which will be the case if the task associated
|
||||||
|
with the thread originally deleted itself rather than being deleted by a
|
||||||
|
different task. */
|
||||||
|
if( pxThreadState->pvThread != NULL )
|
||||||
|
{
|
||||||
|
WaitForSingleObject( pvInterruptEventMutex, INFINITE );
|
||||||
|
|
||||||
|
CloseHandle( pxThreadState->pvThread );
|
||||||
TerminateThread( pxThreadState->pvThread, 0 );
|
TerminateThread( pxThreadState->pvThread, 0 );
|
||||||
|
|
||||||
ReleaseMutex( pvInterruptEventMutex );
|
ReleaseMutex( pvInterruptEventMutex );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortCloseRunningThread( void *pvTaskToDelete, volatile portBASE_TYPE *pxPendYield )
|
||||||
|
{
|
||||||
|
xThreadState *pxThreadState;
|
||||||
|
void *pvThread;
|
||||||
|
|
||||||
|
/* Find the handle of the thread being deleted. */
|
||||||
|
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );
|
||||||
|
pvThread = pxThreadState->pvThread;
|
||||||
|
|
||||||
|
/* Raise the Windows priority of the thread to ensure the FreeRTOS scheduler
|
||||||
|
does not run and swap it out before it is closed. If that were to happen
|
||||||
|
the thread would never run again and effectively be a thread handle and
|
||||||
|
memory leak. */
|
||||||
|
SetThreadPriority( pvThread, THREAD_PRIORITY_ABOVE_NORMAL );
|
||||||
|
|
||||||
|
/* This function will not return, therefore a yield is set as pending to
|
||||||
|
ensure a context switch occurs away from this thread on the next tick. */
|
||||||
|
*pxPendYield = pdTRUE;
|
||||||
|
|
||||||
|
/* Mark the thread associated with this task as invalid so
|
||||||
|
vPortDeleteThread() does not try to terminate it. */
|
||||||
|
pxThreadState->pvThread = NULL;
|
||||||
|
|
||||||
|
/* Close the thread. */
|
||||||
|
CloseHandle( pvThread );
|
||||||
|
ExitThread( 0 );
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortEndScheduler( void )
|
void vPortEndScheduler( void )
|
||||||
|
|
|
@ -685,6 +685,13 @@ tskTCB * pxNewTCB;
|
||||||
if( pxTCB == pxCurrentTCB )
|
if( pxTCB == pxCurrentTCB )
|
||||||
{
|
{
|
||||||
configASSERT( uxSchedulerSuspended == 0 );
|
configASSERT( uxSchedulerSuspended == 0 );
|
||||||
|
|
||||||
|
/* The pre-delete hook is primarily for the Windows simulator,
|
||||||
|
in which Windows specific clean up operations are performed,
|
||||||
|
after which it is not possible to yield away from this task -
|
||||||
|
hence xYieldPending is used to latch that a context switch is
|
||||||
|
required. */
|
||||||
|
portPRE_DELETE_HOOK( pxTCB, &xYieldPending );
|
||||||
portYIELD_WITHIN_API();
|
portYIELD_WITHIN_API();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1896,7 +1903,7 @@ void vTaskSwitchContext( void )
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait )
|
void vTaskPlaceOnEventList( xList * const pxEventList, const portTickType xTicksToWait )
|
||||||
{
|
{
|
||||||
portTickType xTimeToWake;
|
portTickType xTimeToWake;
|
||||||
|
|
||||||
|
@ -1948,7 +1955,7 @@ portTickType xTimeToWake;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait )
|
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, const portTickType xTicksToWait )
|
||||||
{
|
{
|
||||||
portTickType xTimeToWake;
|
portTickType xTimeToWake;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue