rtel wrote on Saturday, October 21, 2006:
I think there may be an easy option if you want a task to block without a timeout on a queue.
If a task appears in a delayed task list it is blocked with a timeout. When the time out occurs the task will be woken from within the tick ISR.
If a task appears on the suspended task list it remains on the suspended task list until such a time that another task or an ISR un-suspends it. It can therefore remain on the suspended task list indefinitely.
When a task blocks on a queue vTaskPlaceOnEventList() is called. This places the calling task onto a delayed task list - to be woken when the block time expires. If instead the task were to be placed on a suspended task list it would remain blocked/suspended until such a time that the queue event it was waiting for occurred.
Within vTaskPlaceOnEventList() the two lines:
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 ) );
}
would become:
if( xTimeToWake == BLOCK_FOREVER )
{
____vListInsertEnd( ( xList * ) xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
}
else 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 ) );
}
This would result in the event list item being on the queue in priority order, and the generic (state) list item being on the suspended list.
I have not tested this or done a full analysis, but it seems straight forward. The problem would be what value to use for BLOCK_FOREVER, as the block time is an unsigned value all possible values are valid block times. You could take portMAX_DELAY to mean that you want to block for ever, or you could introduce a new parameter to the function to indicate that you wanted to block forever - in which case the block time would be ignored.
Regards.