1st iteration: vTaskGetCurrentBlocker

This commit is contained in:
David Chalco 2020-03-25 14:15:42 -07:00
parent 464695a4f2
commit b9dab369b1
2 changed files with 150 additions and 1 deletions

View file

@ -147,6 +147,26 @@ typedef struct xTASK_STATUS
configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} TaskStatus_t; } TaskStatus_t;
/* Possibe return values for vTaskGetCurrentBlocker() */
typedef enum
{
eBlockedForEvent = 0,
eBlockedForNotification,
eBlockedForTime,
eNotBlocked
} eBlockedStatus;
/* Used with eTaskGetCurrentBlocker to return either a pointer or a integer */
typedef struct XTASK_BLOCKED_STATUS
{
eBlockedStatus eStatus;
union
{
List_t *pxEventList;
TickType_t xUntilTick;
};
} TaskBlockedStatus_t;
/* Possible return values for eTaskConfirmSleepModeStatus(). */ /* Possible return values for eTaskConfirmSleepModeStatus(). */
typedef enum typedef enum
{ {
@ -155,6 +175,7 @@ typedef enum
eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */
} eSleepModeStatus; } eSleepModeStatus;
/** /**
* Defines the priority used by the idle task. This must not be modified. * Defines the priority used by the idle task. This must not be modified.
* *
@ -1771,6 +1792,38 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
*/ */
uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
/**
* task.h
* <PRE>void vTaskGetCurrentBlocker( TaskHandle_t xTask, TaskBlockedStatus_t * pxBlockedStatus )</PRE>
*
* INCLUDE_vTaskGetCurrentBlocker must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Note, if xTask is NULL or is the running task this function the return eStatus will always be eNotBlocked because
* the task can not be blocked if it is running.
*
* TaskBlockedStatus_t holds an eStatus member and both pxEventList in xUntilTick in union. eStatus will always be
* be set, however pxEventList will only ever be assigned the blocking event list when the task is eBlockedForEvent.
* When the the task is eBlockedForTime, xUntilTick will be assigned the tick index at which the task can exit
* the Blocked state.
*
* eStatus will be eBlockedForEvent if the task is blocked and waiting on a RTOS object event list.
* If it is not eBlockedEvent, eStatus will be eBlockedForNotification if config_USENOTIFICATIONS is set to 1
* and the task is waiting for a notification. If the task is blocked but neither eBlockedForEvent nor eBlockedForNotification,
* eStatus will be eBlockedForTime and xUntilTick will be assigned the tick value at which the task can exit the blocked state.
* list. If the task is not blocked, eStatus will be eNotBlocked.
*
* @param xTask The handle of the task to query. If xTask == NULL, the current running task is evaluated.
*
* @param pxBlockerStatus The struct for storing eStatus and union of xUntilTick or pxEventList.
*
* \defgroup vTaskGetCurrentBlocker vTaskGetCurrentBlocker
* \ingroup TaskUtils
*
*/
void vTaskGetCurrentBlocker( TaskHandle_t xTask, TaskBlockedStatus_t * pxBlockedStatus ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <PRE>BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );</PRE> * <PRE>BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );</PRE>
@ -2357,7 +2410,6 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const
*/ */
BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION;
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
*----------------------------------------------------------*/ *----------------------------------------------------------*/

97
tasks.c
View file

@ -5177,6 +5177,103 @@ TickType_t uxReturn;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( INCLUDE_eTaskGetBlocker == 1 )
void vTaskGetCurrentBlocker(TaskHandle_t xTask, TaskBlockedStatus_t* pxBlockedStatus)
{
List_t const *pxStateList, * pxEventList, * pxDelayedList, * pxOverflowDelayedList
const TCB_t * const pxTCB = xTask;
TickType_t xStateListItemValue = 0u;
#if (configUSE_TASK_NOTIFICATIONS == 1)
uint8_t ucNotifyState = 0u;
#endif
memset(pxBlockedStatus, 0u, sizeof(TaskBlockedStatus_t));
pxBlockedStatus = eNotBlocked;
/* Per convention NULL operates for current task.
Current task can't be blocked if its running this function */
if (pxTCB != pxCurrentTCB && pxTCB != NULL)
{
/* Take a snapshot of data that could otherwise change during this function call */
taskENTER_CRITICAL();
{
pxStateList = listLIST_ITEM_CONTAINER(&(pxTCB->xStateListItem));
pxEventList = listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem));
pxDelayedList = pxDelayedTaskList;
pxOverflowDelayedList = pxOverflowDelayedTaskList;
xStateListItemValue = pxTCB->xStateListItem->xItemValue;
#if (configUSE_TASK_NOTIFICATIONS == 1)
{
ucNotifyState = pxTCB->ucNotifyState;
}
#endif
}
taskEXIT_CRITICAL();
if (pxStateList == pxDelayedList || pxStateList == pxOverflowDelayedList)
{
if (pxEventList != NULL)
{
/* Blocked waiting for event*/
pxBlockedStatus->eStatus = eBlockedForEvent;
pxBlockedStatus->pxEventList = pxEventList;
}
#if (configUSE_TASK_NOTIFICATIONS == 1)
else if (ucNotifyState == taskWAITING_NOTIFICATION)
{
/* Blocked waiting for notification*/
pxBlockedStatus->eStatus = eBlockedForNotification;
}
#endif
else
{
/* Blocked but not for event nor notification, which by elimination leaves temporal block.
Note that while in delayed lists, a task will block until at least the tick stored in xStateListItem->xItemValue */
pxBlockedStatus->eStatus = eBlockedForTime;
pxBlockedStatus->xUntilTick = xStateListItemValue;
}
}
#if (INCLUDE_vTaskSuspend == 1)
else if (pxStateList == &xSuspendedTaskList)
{
/* When prvAddCurrentTaskToDelayedLists(portMAX_DELAY, pdTRUE) and INCLUDE_vTaskSuspend == 1, the task can
block indefinitely and is instead placed on the xSuspendTaskList. */
if (pxEventList != NULL)
{
eBlockedStatus->eStatus = eBlockedForEvent;
eBlockedStatus->eEventList = pxEventList;
}
else
{
#if (configUSE_TASK_NOTIFICATIONS)
if (ucNotifyState == taskWAITING_NOTIFICATION)
{
eBlockedStatus = eBlockedForNotification;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#else
mtCOVERAGE_TEST_MARKER();
#endif
}
}
#endif
else
{
pxBlockedStatus->eStatus = eNotBlocked;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif
/*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{ {
TickType_t xTimeToWake; TickType_t xTimeToWake;