PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;\r
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;\r
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;\r
-PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;\r
+PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;\r
PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;\r
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;\r
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;\r
{\r
TCB_t *pxTCB = NULL;\r
BaseType_t xAlreadyYielded = pdFALSE;\r
+TickType_t xTicksToNextUnblockTime;\r
\r
/* If uxSchedulerSuspended is zero then this function does not match a\r
previous call to vTaskSuspendAll(). */\r
they should be processed now. This ensures the tick count does\r
not slip, and that any delayed tasks are resumed at the correct\r
time. */\r
+ while( xPendedTicks > ( TickType_t ) 0 )\r
{\r
- UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */\r
+ /* Calculate how far into the future the next task will\r
+ leave the Blocked state because its timeout expired. If\r
+ there are no tasks due to leave the blocked state between\r
+ the time now and the time at which the tick count overflows\r
+ then xNextTaskUnblockTime will the tick overflow time.\r
+ This means xNextTaskUnblockTime can never be less than\r
+ xTickCount, and the following can therefore not\r
+ underflow. */\r
+ configASSERT( xNextTaskUnblockTime >= xTickCount );\r
+ xTicksToNextUnblockTime = xNextTaskUnblockTime - xTickCount;\r
\r
- if( uxPendedCounts > ( UBaseType_t ) 0U )\r
+ /* Don't want to move the tick count more than the number\r
+ of ticks that are pending, so cap if necessary. */\r
+ if( xTicksToNextUnblockTime > xPendedTicks )\r
{\r
- do\r
- {\r
- if( xTaskIncrementTick() != pdFALSE )\r
- {\r
- xYieldPending = pdTRUE;\r
- }\r
- else\r
- {\r
- mtCOVERAGE_TEST_MARKER();\r
- }\r
- --uxPendedCounts;\r
- } while( uxPendedCounts > ( UBaseType_t ) 0U );\r
+ xTicksToNextUnblockTime = xPendedTicks;\r
+ }\r
\r
- uxPendedTicks = 0;\r
+ if( xTicksToNextUnblockTime == 0 )\r
+ {\r
+ /* xTicksToNextUnblockTime could be zero if the tick\r
+ count is about to overflow and xTicksToNetUnblockTime\r
+ holds the time at which the tick count will overflow\r
+ (rather than the time at which the next task will\r
+ unblock). Set to 1 otherwise xPendedTicks won't be\r
+ decremented below. */\r
+ xTicksToNextUnblockTime = ( TickType_t ) 1;\r
}\r
- else\r
+ else if( xTicksToNextUnblockTime > ( TickType_t ) 1 )\r
{\r
- mtCOVERAGE_TEST_MARKER();\r
+ /* Move the tick count one short of the next unblock\r
+ time, then call xTaskIncrementTick() to move the tick\r
+ count up to the next unblock time to unblock the task,\r
+ if any. This will also swap the blocked task and\r
+ overflow blocked task lists if necessary. */\r
+ xTickCount += ( xTicksToNextUnblockTime - ( TickType_t ) 1 );\r
}\r
+ xYieldPending |= xTaskIncrementTick();\r
+\r
+ /* Adjust for the number of ticks just added to\r
+ xTickCount and go around the loop again if\r
+ xTicksToCatchUp is still greater than 0. */\r
+ xPendedTicks -= xTicksToNextUnblockTime;\r
}\r
\r
if( xYieldPending != pdFALSE )\r
#endif /* configUSE_TICKLESS_IDLE */\r
/*----------------------------------------------------------*/\r
\r
+BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )\r
+{\r
+BaseType_t xYieldRequired = pdFALSE;\r
+\r
+ /* Must not be called with the scheduler suspended as the implementation\r
+ relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */\r
+ configASSERT( uxSchedulerSuspended == 0 );\r
+\r
+ /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when\r
+ the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */\r
+ vTaskSuspendAll();\r
+ xPendedTicks += xTicksToCatchUp;\r
+ xYieldRequired = xTaskResumeAll();\r
+\r
+ return xYieldRequired;\r
+}\r
+/*----------------------------------------------------------*/\r
+\r
#if ( INCLUDE_xTaskAbortDelay == 1 )\r
\r
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )\r
{\r
/* Guard against the tick hook being called when the pended tick\r
count is being unwound (when the scheduler is being unlocked). */\r
- if( uxPendedTicks == ( UBaseType_t ) 0U )\r
+ if( xPendedTicks == ( TickType_t ) 0 )\r
{\r
vApplicationTickHook();\r
}\r
}\r
else\r
{\r
- ++uxPendedTicks;\r
+ ++xPendedTicks;\r
\r
/* The tick hook gets called at regular intervals, even if the\r
scheduler is locked. */\r
\r
#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )\r
\r
- TickType_t xTaskGetIdleRunTimeCounter( void )\r
+ uint32_t ulTaskGetIdleRunTimeCounter( void )\r
{\r
return xIdleTaskHandle->ulRunTimeCounter;\r
}\r